zoukankan      html  css  js  c++  java
  • 使用JAAS文件登陆kerberos(zookeeper)

    Kerberos 5 Configuration

    Since the SPNEGO mechanism will call JGSS, which in turns calls the Kerberos V5 login module to do real works. Kerberos 5 configurations are needed. which includes:

    • Some way to provide Kerberos configurations. This can be achieved with the Java system property java.security.krb5.conf. For example:
                java -Djava.security.krb5.conf=krb5.conf 
                     -Djavax.security.auth.useSubjectCredsOnly=false 
                     ClassName
    
    • A JAAS config file denoting what login module to use. HTTP SPNEGO codes will look for the standard entry named com.sun.security.jgss.krb5.initiate.

    For example, you can provide a file spnegoLogin.conf:

              com.sun.security.jgss.krb5.initiate {
                  com.sun.security.auth.module.Krb5LoginModule
                      required useTicketCache=true;
              };
    

    and run java with:

                java -Djava.security.krb5.conf=krb5.conf 
                     -Djava.security.auth.login.config=spnegoLogin.conf 
                     -Djavax.security.auth.useSubjectCredsOnly=false 
                     ClassName
    

    JAAS:https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzaha/rzahajaas10.htm

    ZooKeeperSaslClient

    在使用带Kerberos的zookeeper时,连接前需要进行认证,但是需要通过jaas机制去登陆Kerberos,这时候需要给JVM设置jaas.conf配置文件,zookeeper源码种等登陆模块如下:

    public ZooKeeperSaslClient(String serverPrincipal, ZKClientConfig clientConfig) throws LoginException {
            this.saslState = ZooKeeperSaslClient.SaslState.INITIAL;
            this.gotLastPacket = false;
            String clientSection = clientConfig.getProperty("zookeeper.sasl.clientconfig", "Client");
            this.clientConfig = clientConfig;
            AppConfigurationEntry[] entries = null;
            Object runtimeException = null;
    
            try {
                entries = Configuration.getConfiguration().getAppConfigurationEntry(clientSection);
            } catch (SecurityException var8) {
                runtimeException = var8;
            } catch (IllegalArgumentException var9) {
                runtimeException = var9;
            }
    
            if (entries != null) {
                this.configStatus = "Will attempt to SASL-authenticate using Login Context section '" + clientSection + "'";
                this.saslClient = this.createSaslClient(serverPrincipal, clientSection);
            } else {
                this.saslState = ZooKeeperSaslClient.SaslState.FAILED;
                String explicitClientSection = clientConfig.getProperty("zookeeper.sasl.clientconfig");
                if (explicitClientSection != null) {
                    if (runtimeException != null) {
                        throw new LoginException("Zookeeper client cannot authenticate using the " + explicitClientSection + " section of the supplied JAAS configuration: '" + clientConfig.getJaasConfKey() + "' because of a RuntimeException: " + runtimeException);
                    }
    
                    throw new LoginException("Client cannot SASL-authenticate because the specified JAAS configuration section '" + explicitClientSection + "' could not be found.");
                }
    
                String msg = "Will not attempt to authenticate using SASL ";
                if (runtimeException != null) {
                    msg = msg + "(" + runtimeException + ")";
                } else {
                    msg = msg + "(unknown error)";
                }
    
                this.configStatus = msg;
                this.isSASLConfigured = false;
                if (clientConfig.getJaasConfKey() != null) {
                    if (runtimeException != null) {
                        throw new LoginException("Zookeeper client cannot authenticate using the '" + clientConfig.getProperty("zookeeper.sasl.clientconfig", "Client") + "' section of the supplied JAAS configuration: '" + clientConfig.getJaasConfKey() + "' because of a RuntimeException: " + runtimeException);
                    }
    
                    throw new LoginException("No JAAS configuration section named '" + clientConfig.getProperty("zookeeper.sasl.clientconfig", "Client") + "' was found in specified JAAS configuration file: '" + clientConfig.getJaasConfKey() + "'.");
                }
            }
    
        }
    

    可以看处,默认读取的时Client模块下的配置,也会从zookeeper.sasl.clientconfig种读取。其登陆代码如下:

    private SaslClient createSaslClient(String servicePrincipal, String loginContext) throws LoginException {
            try {
                if (!this.initializedLogin) {
                    synchronized(this) {
                        if (this.login == null) {
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("JAAS loginContext is: " + loginContext);
                            }
    
                            this.login = new Login(loginContext, new ZooKeeperSaslClient.ClientCallbackHandler((String)null), this.clientConfig);
                            this.login.startThreadIfNeeded();
                            this.initializedLogin = true;
                        }
                    }
                }
    
                Subject subject = this.login.getSubject();
                SaslClient saslClient;
                if (subject.getPrincipals().isEmpty()) {
                    LOG.info("Client will use DIGEST-MD5 as SASL mechanism.");
                    String[] mechs = new String[]{"DIGEST-MD5"};
                    String username = (String)((String)subject.getPublicCredentials().toArray()[0]);
                    String password = (String)((String)subject.getPrivateCredentials().toArray()[0]);
                    saslClient = Sasl.createSaslClient(mechs, username, "zookeeper", "zk-sasl-md5", (Map)null, new ZooKeeperSaslClient.ClientCallbackHandler(password));
                    return saslClient;
                } else {
                    boolean usingNativeJgss = this.clientConfig.getBoolean("sun.security.jgss.native");
                    if (usingNativeJgss) {
                        try {
                            GSSManager manager = GSSManager.getInstance();
                            Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2");
                            GSSCredential cred = manager.createCredential((GSSName)null, 0, krb5Mechanism, 1);
                            subject.getPrivateCredentials().add(cred);
                        } catch (GSSException var16) {
                            LOG.warn("Cannot add private credential to subject; authentication at the server may fail", var16);
                        }
                    }
    
                    Object[] principals = subject.getPrincipals().toArray();
                    Principal clientPrincipal = (Principal)principals[0];
                    KerberosName clientKerberosName = new KerberosName(clientPrincipal.getName());
                    String serverRealm = this.clientConfig.getProperty("zookeeper.server.realm", clientKerberosName.getRealm());
                    KerberosName serviceKerberosName = new KerberosName(servicePrincipal + "@" + serverRealm);
                    final String serviceName = serviceKerberosName.getServiceName();
                    final String serviceHostname = serviceKerberosName.getHostName();
                    final String clientPrincipalName = clientKerberosName.toString();
    
                    try {
                        saslClient = (SaslClient)Subject.doAs(subject, new PrivilegedExceptionAction<SaslClient>() {
                            public SaslClient run() throws SaslException {
                                ZooKeeperSaslClient.LOG.info("Client will use GSSAPI as SASL mechanism.");
                                String[] mechs = new String[]{"GSSAPI"};
                                ZooKeeperSaslClient.LOG.debug("creating sasl client: client=" + clientPrincipalName + ";service=" + serviceName + ";serviceHostname=" + serviceHostname);
                                SaslClient saslClient = Sasl.createSaslClient(mechs, clientPrincipalName, serviceName, serviceHostname, (Map)null, new ZooKeeperSaslClient.ClientCallbackHandler((String)null));
                                return saslClient;
                            }
                        });
                        return saslClient;
                    } catch (Exception var15) {
                        LOG.error("Exception while trying to create SASL client", var15);
                        var15.printStackTrace();
                        return null;
                    }
                }
            } catch (LoginException var18) {
                throw var18;
            } catch (Exception var19) {
                LOG.error("Exception while trying to create SASL client: " + var19);
                return null;
            }
        }
    

    This is jaas.conf:

    Client {
          com.sun.security.auth.module.Krb5LoginModule required
          useKeyTab=true
          doNotPrompt=true
          useTicketCache=true
          principal="test"
          keyTab="/home/keytab/user.keytab";
       };
    
    

    Then set Java Options like :

    --Djava.security.auth.login.config=/data/disk1/conf/jaas.conf -Djavax.security.auth.useSubjectCredsOnly=false 
    

    其他情况下,会使用com.sun.security.jgss.krb5.initiate来登陆,所以jaas.conf的配置如下:

    com.sun.security.jgss.krb5.initiate {
      com.sun.security.auth.module.Krb5LoginModule required
      useKeyTab=true
      keyTab="/data/disk1/conf/test.keytab"
      principal="test"
      doNotPrompt=true;
    };
    
  • 相关阅读:
    Atitit 提升开发进度大方法--高频功能与步骤的优化 类似性能优化
    Atitit 翻页功能的解决方案与版本历史 v4 r49
    Atitit.pagging  翻页功能解决方案专题 与 目录大纲 v3 r44.docx
    Atitit 视图参数解决方案 oracle版和mysql版本 attilax总结.docx
    Atitit easyui翻页组件与vue的集成解决方案attilax总结
    Atitit  技术经理职责与流程表总结
    Atitit 数据库视图与表的wrap与层级查询规范
    Atitit 手机图片备份解决方案attilax总结
    Atitit 提升进度的大原则与方法  高层方法  attilax总结
    Atiitt 使用java语言编写sql函数或存储过程
  • 原文地址:https://www.cnblogs.com/flowerbirds/p/14191839.html
Copyright © 2011-2022 走看看