Делегирование Kerberos: GSSUtil.createSubject возвращает субъект только с основным именем - PullRequest
0 голосов
/ 27 мая 2019

Я делаю делегирование Kerberos.Я заметил, что GSSUtil.createSubject(context.getSrcName(), clientCred) возвращает тему без учетных данных.До этого я сделал GSSCredential clientCred = context.getDelegCred();, который возвращает учетные данные.Изменить: Когда я запускаю свой сервис с одного компьютера в том же домене, он работает, а при доступе с другого компьютера в том же домене - нет.Смутили, какие дополнительные настройки нужны на AD?Любая помощь высоко ценится.

Ниже мой код:

public class KerberosTest {

    public Subject loginImpl(byte[] kerberosTicket, String propertiesFileName) throws Exception {
        System.setProperty("sun.security.krb5.debug", "true");
//        // no effect // System.setProperty("javax.security.auth.useSubjectCredsOnly","false");

        final Krb5LoginModule krb5LoginModule = new Krb5LoginModule();
        Subject serviceUserSubject = new Subject();
        final Map<String,String> optionMap = new HashMap<String,String>();
        HashMap<String, String> shared = new HashMap<>();

            optionMap.put("keyTab", "C:\\kerberos_files\\sapuser.keytab");
            optionMap.put("principal", "HTTP/SAPTEST@EQSECTEST.LOCAL"); // default realm
//            optionMap.put("principal", "kerberosuser"); // default realm
            optionMap.put("useFirstPass", "true");
            optionMap.put("doNotPrompt", "true");
            optionMap.put("refreshKrb5Config", "true");
            optionMap.put("useTicketCache", "false");
            optionMap.put("renewTGT", "false");
            optionMap.put("useKeyTab", "true");
            optionMap.put("storeKey", "true");
            optionMap.put("isInitiator", "true");
            optionMap.put("useSubjectCredsOnly", "false");

            optionMap.put("debug", "true"); // switch on debug of the Java implementation
            krb5LoginModule.initialize(serviceUserSubject, null, shared, optionMap);

            // login using details mentioned inside keytab
            boolean loginOk = krb5LoginModule.login();
            System.out.println("Login success: " + loginOk);

            // This API adds Kerberos Credentials to the the Subject's private credentials set
            boolean commitOk = krb5LoginModule.commit();

        }

        System.out.println("Principal from subject: " + serviceUserSubject.getPrincipals()); // this must display name of user to which the keytab corresponds to



        Subject clientSubject = getClientContext(serviceUserSubject, kerberosTicket);
        System.out.println("Client Subject-> " + clientSubject);
        System.out.println("Client principal-> "+clientSubject.getPrincipals().toArray()[0]);

        return clientSubject;
    }

    // Completes the security context initialisation and returns the client name.
    private Subject getClientContext(Subject subject, final byte[] kerberosTicket) throws PrivilegedActionException {
        Subject clientSubject = Subject.doAs(subject, new KerberosValidateAction(kerberosTicket));
        return clientSubject;
    }

    private class KerberosValidateAction implements PrivilegedExceptionAction<Subject> {
        byte[] kerberosTicket;

        public KerberosValidateAction(byte[] kerberosTicket) {
            this.kerberosTicket = kerberosTicket;
        }

        @Override
        public Subject run() throws Exception {
            GSSManager gssManager = GSSManager.getInstance();
            GSSContext context = gssManager.createContext((GSSCredential) null);

            Oid kerberosOid = new Oid("1.2.840.113554.1.2.2");

//             context.requestCredDeleg(true); // needed when we are demanding ticket from KDC. In our scenario, we are getting ticket from browser(client)

            // Called by the context acceptor upon receiving a token from the peer. This is our context acceptor
            // This method may return an output token which the application will need to send to the peer for further processing by its initSecContext call.
            // We will only accept the incoming token from Peer (browser) and fwd it to third party system
            while (!context.isEstablished()) {
                byte[] nextToken = context.acceptSecContext(kerberosTicket, 0, kerberosTicket.length);
            }

            boolean established = context.isEstablished();
            String user = context.getSrcName().toString();
            String serviceAccnt = context.getTargName().toString();


            //check if the credentials can be delegated
            if (!context.getCredDelegState()) {
                System.out.println("credentials can not be delegated!");
                return null;
            }

            //get the delegated credentials from the calling peer...
            GSSCredential clientCred = context.getDelegCred();
            //Create a Subject out of the delegated credentials.
            //With this Subject the application server can impersonate the client that sent the request.

            Subject clientSubject = GSSUtil.createSubject(context.getSrcName(), clientCred);
            return clientSubject; // ***this contains only principal name and not credentials !!
        }
    }

1 Ответ

0 голосов
/ 30 мая 2019

Я выяснил один важный момент, который я нигде не нашел в документации.-

При настройке пользователя службы Kerberos в AD «Доверять этому пользователю для делегирования (только Kerberos)» вступит в силу только для новых TGT, созданных после сохранения этого изменения.

Например, если пользователь вошел в систему на клиентском компьютере A, скажем, в 10:00.
Администратор разрешает делегирование пользователю службы Kerberos в 10:30.
Когда пользователь нажимает URL-адрес приложения из браузера на компьютере A, делегирование не будет работать, поскольку его TGT создается до включения делегирования (в 10:00).

Еслипользователь выходит из машины A и повторно регистрируется, будет сгенерирован новый TGT.Делегация отлично работает для этого пользователя.

...