在进行构建CI工作流前,先了解下2个概念
GitOps是一种持续交付的方式.它的核心思想是将应用系统的声明性基础架构和应用程序存放在Git的版本库中.
将Git作为交付流水线的核心,每个开发人员都可以提交拉取请求(Pull Request)并使用Git来加速和简化应用程序部署和运维任务.通过使用像Git这样的简单熟悉工具,开发人员可以更高效地将注意力集中在创建新功能而不是运维相关任务上(例如,应用系统安装,配置,迁移等)
通过应用 GitOps ,应用系统的基础架构和应用程序代码可以快速查找来源——基础架构和应用程序代码都存放在 GitLab 、或者 GitHub 等版本控制系统上.这使开发团队可以提高开发和部署速度并提高应用系统可靠性.
将 GitOps 应用在持续交付流水线上,有诸多优势和特点:
在我看来 GitOps 的最大优势就是通过完善的 Git 分支管理来达到管理所有 CI/CD 管道流水线的目的,不同的环境可以对应不同分支,在该环境出现问题时候,可以直接查找对应分支代码,达到快速排查问题的目的.而对于 Git 的熟悉,更是省去学习使用一般 DevOps 工具所需的学习成本和配置时间,开发人员可以无任何培训直接上手使用,进一步降低了时间与人力成本.
持续集成(ContinousIntergration,CI)是一种软件开发实践,即团队开发成员经常集成它们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都需要通过自动化的编译、发布、自动化回归测试来验证,从而尽快地发现集成错误。而这些自动化的操作则由CI软件进行执行。
持续部署(ContinousDelivery,CD)在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境中。交付团队 - >版本控制 - >构建和单元测试 - >自动验收测试(e2e)- > UAT - >发布(部署,DevOps)
Drone 是一个基于Docker容器技术的可扩展的持续集成引擎,用于自动化测试与构建,甚至发布。每个构建都在一个临时的Docker容器中执行,使开发人员能够完全控制其构建环境并保证隔离。开发者只需在项目中包含 .drone.yml
文件,将代码推送到 git 仓库,Drone就能够自动化的进行编译、测试、发布。
官方文档上面大量充斥着0.8
版本的配置文件描述,而最新的版本是1.2.3
,两个版本之间有大量的不同地方,需要大家一点一点的试错摸索,不过读者在读完本篇文章后,就可以很顺畅的编写pipeline了。
描述
我们在进行ci/cd
流程时,应用了deployment
资源时,无法知道修改的pod
是否处在就绪状态,并正常工作。但是我们的应用操作时成功执行了,如果说这时pod
没有正常就绪工作,也就是说我们要改变的pod
没有改变,目标集群运行的还是之前的pod
,如果说我们有对deployment
的不可用pod进行监控,那我们得到的通知时间也是很滞后了,因此,我们需要一个在ci/cd
流程中检查deployment
的所有pod
是否就绪并正常工作
。kubectl-check就是为了解决这个场景而诞生的。
由于种种原因吧,我们在下载k8s组件镜像的时候,常常会遇到下载龟速的问题,很多小伙伴在自己的docker hub中定时同步谷歌镜像,当然国内也有公司为此做了镜像站点, Azure,阿里云等等。
在使用docker hub下载镜像时,需要加上docker的国内加速站点.
常规下载谷歌镜像站点
# docker pull gcr.azk8s.cn/google_containers/pause-amd64:3.1
3.1: Pulling from google_containers/pause-amd64
67ddbfb20a22: Pull complete
Digest: sha256:59eec8837a4d942cc19a52b8c09ea75121acc38114a2c68b98983ce9356b8610
Status: Downloaded newer image for gcr.azk8s.cn/google_containers/pause-amd64:3.1
# docker tag gcr.azk8s.cn/google_containers/pause-amd64:3.1 gcr.io/google_containers/pause-amd64:3.1
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gcr.azk8s.cn/google_containers/pause-amd64 3.1 da86e6ba6ca1 19 months ago 742kB
gcr.io/google_containers/pause-amd64 3.1 da86e6ba6ca1 19 months ago 742kB
这种下载一个镜像还行,如果是多个的话,那就要累死了,为此我写了一个脚本,减轻我们的一些工作。
因为Zabbix没有报警分组和沉默的功能,有时候大规模的产生报警,就会有很多的报警邮件或短信通知,导致了一些不必要的浪费,而Prometheus套件中的AlertManager符合我们的诉求,可以将报警分组聚合进行发送,并且可以在一段时间内沉默报警.这里就以zabbix报警脚本向AlertManager发送报警信息,再由AlertManager处理后通知用户。
Openldap是开源的目录服务实现,windows AD是微软的目录服务现实。现状是有的场景(应用、客户端)跟openldap结合比较容易,有的场景又是必须要用AD,所以几乎不可能弃用其中的任意一种。但同时维护两套系统意味着维护工作大量增加(不仅仅只是增加一倍,要考虑信息分别维护、同步etc等)、出错几率增加。
其中的一种较成熟、使用比较多的解决方案是:openldap使用windows AD的认证,这样只需要在AD上维护一套用户密码即可。
使用lsc项目同步openldap与AD之间的用户信息
什么是LSC? Ldap同步连接器通过在源和目标引用之间读取,转换和比较这些数据来同步来自任何数据源(包括数据库,LDAP目录或文件)的数据。然后,可以使用这些连接器将数据源连续同步到目录,进行单次导入或仅通过输出CSV或LDIF格式报告来比较差异。
LSC提供了一个基于脚本语言的强大转换引擎,可以轻松地动态处理数据。
包含 各种身份管理功能以用于特定于目录的兼容性 - 最明显的是Active Directory(更改密码,帐户状态,上次登录等)。
LSC是一个用Java编写的开源项目,可以在BSD许可下获得。
OS: centos 7.4
OpenLDAP: 请按照在CentOS 7上安装OpenLDAP服务器文章进行安装部署,并添加2个测试用户和组
AD: 请按照Windows Server 2016安装AD并开启SSL文章进行安装部署,并添加2个测试用户
cat > /etc/yum.repos.d/lsc-project.repo << EOF
[lsc-project]
name=LSC project packages
baseurl=http://lsc-project.org/rpm/noarch
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-LTB-project
EOF
rpm --import http://ltb-project.org/wiki/lib/RPM-GPG-KEY-LTB-project
yum install -y lsc java
LSC会将OpenLDAP中的数据源同步到Active Directory,即lsc.xml的内容:
echo '192.168.77.135 WIN-V5SBNPSNFOM.lework.com' >> /etc/hosts
mkdir /etc/lsc/openldap2ad/
cp /etc/lsc/logback.xml /etc/lsc/openldap2ad
cat /etc/lsc/openldap2ad/lsc.xml
<?xml version="1.0" encoding="utf-8"?>
<lsc xmlns="http://lsc-project.org/XSD/lsc-core-2.1.xsd" revision="0">
<connections>
<ldapConnection>
<name>ad</name>
<url>ldaps://WIN-V5SBNPSNFOM.lework.com:636/dc=lework,dc=com</url>
<username>administrator@lework.com</username>
<password>Admin123</password>
<authentication>SIMPLE</authentication>
<pageSize>1000</pageSize>
</ldapConnection>
<ldapConnection>
<name>openldap</name>
<url>ldap://127.0.0.1:389/dc=lework,dc=com</url>
<username>cn=Manager,dc=lework,dc=com</username>
<password>123456</password>
<authentication>SIMPLE</authentication>
</ldapConnection>
</connections>
<tasks>
<task>
<name>a-PeopleSyncTask</name>
<bean>org.lsc.beans.SimpleBean</bean>
<ldapSourceService>
<name>openldap-source-service</name>
<connection reference="openldap"/>
<baseDn>ou=people,dc=lework,dc=com</baseDn>
<pivotAttributes>
<string>uid</string>
</pivotAttributes>
<fetchedAttributes>
<string>description</string>
<string>cn</string>
<string>sn</string>
<string>givenName</string>
<string>displayName</string>
<string>userPassword</string>
<string>objectClass</string>
<string>uid</string>
<string>mail</string>
<string>title</string>
</fetchedAttributes>
<getAllFilter><![CDATA[(objectClass=inetOrgPerson)]]></getAllFilter>
<getOneFilter><![CDATA[(&(objectClass=inetOrgPerson)(uid={uid}))]]></getOneFilter>
<cleanFilter><![CDATA[(&(objectClass=inetOrgPerson)(uid={sAMAccountName}))]]></cleanFilter>
</ldapSourceService>
<ldapDestinationService>
<name>ad-dst-service</name>
<connection reference="ad"/>
<baseDn>CN=Users,DC=lework,DC=com</baseDn>
<pivotAttributes>
<string>samAccountName</string>
</pivotAttributes>
<fetchedAttributes>
<string>description</string>
<string>cn</string>
<string>sn</string>
<string>givenName</string>
<string>objectClass</string>
<string>title</string>
<string>displayName</string>
<string>samAccountName</string>
<string>userPrincipalName</string>
<string>unicodePwd</string>
<string>pwdLastSet</string>
<string>userAccountControl</string>
</fetchedAttributes>
<getAllFilter><![CDATA[(objectClass=user)]]></getAllFilter>
<getOneFilter><![CDATA[(&(objectClass=user)(sAMAccountName={uid}))]]></getOneFilter>
</ldapDestinationService>
<propertiesBasedSyncOptions>
<mainIdentifier>"CN=" + srcBean.getDatasetFirstValueById("cn") + ", CN=Users,DC=lework,DC=com"</mainIdentifier>
<defaultDelimiter>;</defaultDelimiter>
<defaultPolicy>FORCE</defaultPolicy>
<conditions>
<create>true</create>
<update>true</update>
<delete>false</delete>
<changeId>true</changeId>
</conditions>
<dataset>
<name>description</name>
<policy>FORCE</policy>
<forceValues>
<string>js:srcBean.getDatasetFirstValueById("sn").toUpperCase() + " (" + srcBean.getDatasetFirstValueById("mail") + ")"</string>
</forceValues>
</dataset>
<dataset>
<name>samAccountName</name>
<policy>KEEP</policy>
<createValues>
<string>js:srcBean.getDatasetFirstValueById("uid")</string>
</createValues>
</dataset>
<dataset>
<name>userPrincipalName</name>
<policy>FORCE</policy>
<forceValues>
<string>js:srcBean.getDatasetFirstValueById("uid") + "@lework.com"</string>
</forceValues>
</dataset>
<dataset>
<name>objectClass</name>
<policy>FORCE</policy>
<createValues>
<string>"user"</string>
<string>"organizationalPerson"</string>
<string>"person"</string>
<string>"top"</string>
</createValues>
</dataset>
<dataset>
<name>userAccountControl</name>
<policy>KEEP</policy>
<createValues>
<string>AD.userAccountControlSet( "0", [AD.UAC_SET_NORMAL_ACCOUNT])</string>
</createValues>
</dataset>
<dataset>
<!-- unicodePwd = "changeit" at creation (requires SSL connection to AD) -->
<name>unicodePwd</name>
<policy>KEEP</policy>
<createValues>
<string>AD.getUnicodePwd("Admin123")</string>
</createValues>
</dataset>
<dataset>
<!-- pwdLastSet = 0 to force user to change password on next connection -->
<name>pwdLastSet</name>
<policy>KEEP</policy>
<createValues>
<string>"0"</string>
</createValues>
</dataset>
</propertiesBasedSyncOptions>
</task>
<task>
<name>b-GroupSyncTask</name>
<bean>org.lsc.beans.SimpleBean</bean>
<asyncLdapSourceService>
<name>group-source-service</name>
<connection reference="openldap"/>
<baseDn>ou=Group,dc=lework,dc=com</baseDn>
<pivotAttributes>
<string>cn</string>
</pivotAttributes>
<fetchedAttributes>
<string>cn</string>
<string>description</string>
<string>memberUid</string>
</fetchedAttributes>
<getAllFilter><![CDATA[(objectClass=posixGroup)]]></getAllFilter>
<getOneFilter><![CDATA[(&(objectClass=posixGroup)(cn={cn}))]]></getOneFilter>
<cleanFilter><![CDATA[(&(objectClass=posixGroup)(cn={cn}))]]></cleanFilter>
<serverType>OpenLDAP</serverType>
</asyncLdapSourceService>
<ldapDestinationService>
<name>group-dst-service</name>
<connection reference="ad"/>
<baseDn>CN=Users,DC=lework,DC=com</baseDn>
<pivotAttributes>
<string>cn</string>
</pivotAttributes>
<fetchedAttributes>
<string>cn</string>
<string>description</string>
<string>member</string>
<string>objectClass</string>
</fetchedAttributes>
<getAllFilter><![CDATA[(objectClass=group)]]></getAllFilter>
<getOneFilter><![CDATA[(&(objectClass=group)(cn={cn}))]]></getOneFilter>
</ldapDestinationService>
<propertiesBasedSyncOptions>
<mainIdentifier>js:"cn=" + javax.naming.ldap.Rdn.escapeValue(srcBean.getDatasetFirstValueById("cn")) + ",CN=Users,DC=lework,DC=com"</mainIdentifier>
<defaultDelimiter>;</defaultDelimiter>
<defaultPolicy>FORCE</defaultPolicy>
<conditions>
<create>true</create>
<update>true</update>
<delete>false</delete>
<changeId>true</changeId>
</conditions>
<dataset>
<name>objectclass</name>
<policy>KEEP</policy>
<createValues>
<string>"group"</string>
<string>"top"</string>
</createValues>
</dataset>
<dataset>
<name>member</name>
<policy>FORCE</policy>
<forceValues>
<string> <![CDATA[
rdjs:
var membersSrcDn = srcBean.getAttributeValuesById("memberUid").toArray();
var membersDstDn = [];
for (var i=0; i<membersSrcDn.length; i++) {
try {
membersSrcDn[i] = ldap.attribute(ldap.list("CN=Users","(sAMAccountName=" + (membersSrcDn[i]) + ")").get(0), 'distinguishedName').get(0)
} catch (e) {
membersSrcDn[i]=null;
}
}
var j=0;
for (var i=0; i<membersSrcDn.length; i++) {
if (membersSrcDn[i]!=null) membersDstDn[j++]=membersSrcDn[i];
}
membersDstDn;
]]> </string>
</forceValues>
</dataset>
</propertiesBasedSyncOptions>
</task>
</tasks>
</lsc>
lsc文件主要配置
<connections></connections> 配置ldap的连接信息
<pageSize></pageSize> 指定了数目
<tasks></tasks> 配置的是同步任务
task 具体配置
<name>a-People</name> 指定task名称
<ldapSourceService></ldapSourceService> 指定task的源ldap配置
<ldapDestinationService></ldapDestinationService> 指定task的目的ldap配置
<propertiesBasedSyncOptions>
</propertiesBasedSyncOptions> 同步属性操作
<mainIdentifier></mainIdentifier> 指定同步目的的dn位置
AD.getUnicodePwd("Admin123") 指定openldap同步到ad域中的用户密码
<conditions> 这个是指定对对象的操作
<create>true</create> 可以创建
<update>true</update> 可以更新
<delete>false</delete> 可以删除,这个选项可以保持src和dest ldap的数据一致
<changeId>true</changeId> 可以修改
</conditions>
针对member
属性js脚本的说明
membersSrcDn
distinguishedName
,将获取的值赋值给membersSrcDn数组,如果没找到则为null
.null
的成员复制给membersDstDn
membersDstDn
数组返回给LSC简而言之,就是从AD传来的用户组里的用户是否在OpenLDAP中存在,如果存在,就在OpenLDAP中设置用户组关系,不存在就不设置。
设置ad域的证书
因为需要更改ad域中的用户密码,必须使用ldaps连接才能更改。
可以通过在Active Directory服务器上执行此命令来导出证书
certutil -ca.cert client.crt
将到处的证书放在/root/openldap/client.crt
导入证书
cd "$(dirname $(dirname `readlink -f /etc/alternatives/java`))/lib/security/"
../../bin/keytool -import -file /root/openldap/client.crt -keystore jssecacerts
输入密钥库口令:
所有者: CN=lework-WIN-V5SBNPSNFOM-CA, DC=lework, DC=com
发布者: CN=lework-WIN-V5SBNPSNFOM-CA, DC=lework, DC=com
序列号: 29be7c115db30cb0406ef332495fefa0
有效期为 Wed Jul 24 18:21:06 CST 2019 至 Tue Jul 24 18:31:06 CST 2029
证书指纹:
MD5: 16:07:17:D6:A1:CE:F1:1C:45:90:DF:5E:5F:5C:D9:93
SHA1: D5:3A:9C:95:FF:5E:A9:62:38:AA:DF:8B:9E:DA:6A:EC:84:4C:8E:76
SHA256: 6D:97:5C:5D:5A:F6:92:5C:4E:0B:60:2A:FC:E5:4C:4C:21:16:6F:E5:C0:96:C3:35:4F:D3:F8:36:59:58:41:46
签名算法名称: SHA256withRSA
主体公共密钥算法: 2048 位 RSA 密钥
版本: 3
扩展:
#1: ObjectId: 1.3.6.1.4.1.311.21.1 Criticality=false
0000: 02 01 00 ...
#2: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
CA:true
PathLen:2147483647
]
#3: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
DigitalSignature
Key_CertSign
Crl_Sign
]
#4: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: D3 14 63 41 56 1F CB C4 E6 1B 2B E5 90 FD 86 B1 ..cAV.....+.....
0010: 85 E3 AA D0 ....
]
]
是否信任此证书? [否]: 是
证书已添加到密钥库中
口令为域密码
执行同步
# 测试任务
/usr/bin/lsc -f /etc/lsc/openldap2ad -s all -c all -n
......
七月 25 11:35:21 - INFO - Starting sync for a-PeopleSyncTask
七月 25 11:35:23 - INFO - All entries: 2, to modify entries: 2, successfully modified entries: 0, errors: 0
七月 25 11:35:23 - INFO - Starting clean for a-PeopleSyncTask
七月 25 11:35:23 - INFO - All entries: 6, to modify entries: 0, successfully modified entries: 0, errors: 0
七月 25 11:35:23 - INFO - Starting sync for b-GroupSyncTask
七月 25 11:35:23 - INFO - All entries: 2, to modify entries: 2, successfully modified entries: 0, errors: 0
七月 25 11:35:23 - INFO - Starting clean for b-GroupSyncTask
七月 25 11:35:23 - INFO - All entries: 20, to modify entries: 0, successfully modified entries: 0, errors: 0
# 执行同步
/usr/bin/lsc -f /etc/lsc/openldap2ad -s all -c all
.....
七月 25 11:36:15 - INFO - Starting sync for a-PeopleSyncTask
七月 25 11:36:17 - INFO - # Adding new object CN=ldapuser1, CN=Users,DC=lework,DC=com for a-PeopleSyncTask
# Thu Jul 25 11:36:17 CST 2019
dn: CN=ldapuser1, CN=Users,DC=lework,DC=com
changetype: add
unicodePwd:: IgBBAGQAbQBpAG4AMQAyADMAIgA=
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
samAccountName: ldapuser1
description: LDAPUSER1 ()
cn: ldapuser1
sn: ldapuser1
userPrincipalName: ldapuser1@lework.com
userAccountControl: 512
pwdLastSet: 0
七月 25 11:36:17 - INFO - # Adding new object CN=ldapuser2, CN=Users,DC=lework,DC=com for a-PeopleSyncTask
# Thu Jul 25 11:36:17 CST 2019
dn: CN=ldapuser2, CN=Users,DC=lework,DC=com
changetype: add
unicodePwd:: IgBBAGQAbQBpAG4AMQAyADMAIgA=
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
samAccountName: ldapuser2
description: LDAPUSER2 ()
cn: ldapuser2
sn: ldapuser2
userPrincipalName: ldapuser2@lework.com
userAccountControl: 512
pwdLastSet: 0
七月 25 11:36:17 - INFO - All entries: 2, to modify entries: 2, successfully modified entries: 2, errors: 0
七月 25 11:36:17 - INFO - Starting clean for a-People
七月 25 11:36:17 - INFO - All entries: 8, to modify entries: 0, successfully modified entries: 0, errors: 0
七月 25 11:36:17 - INFO - Starting sync for b-GroupSyncTask
七月 25 11:36:17 - INFO - # Adding new object cn=ldapgroup2,CN=Users,DC=lework,DC=com for b-GroupSyncTask
# Thu Jul 25 11:36:17 CST 2019
dn: cn=ldapgroup2,CN=Users,DC=lework,DC=com
changetype: add
member: CN=ldapuser2,CN=Users,DC=lework,DC=com
objectClass: group
objectClass: top
cn: ldapgroup2
七月 25 11:36:17 - INFO - # Adding new object cn=ldapgroup1,CN=Users,DC=lework,DC=com for b-GroupSyncTask
# Thu Jul 25 11:36:17 CST 2019
dn: cn=ldapgroup1,CN=Users,DC=lework,DC=com
changetype: add
member: CN=ldapuser1,CN=Users,DC=lework,DC=com
objectClass: group
objectClass: top
cn: ldapgroup1
七月 25 11:36:17 - INFO - All entries: 2, to modify entries: 2, successfully modified entries: 2, errors: 0
七月 25 11:36:17 - INFO - Starting clean for b-GroupSyncTask
七月 25 11:36:17 - INFO - All entries: 22, to modify entries: 0, successfully modified entries: 0, errors: 0
可以看到同步了2个用户和2个组,没有清理任务数据
AD中也能看到同步的用户和组,注意,同步的用户(密码:Admin123)首次登陆需要更改密码
LSC会将Active Directory中的数据源同步到OpenLDAP,即lsc.xml的内容:
mkdir /etc/lsc/ad2openldap/
cp /etc/lsc/logback.xml /etc/lsc/openldap2ad
cat /etc/lsc/ad2openldap/lsc.xml
<?xml version="1.0" encoding="utf-8"?>
<lsc xmlns="http://lsc-project.org/XSD/lsc-core-2.1.xsd" revision="0">
<connections>
<ldapConnection>
<name>ad</name>
<url>ldap://WIN-V5SBNPSNFOM.lework.com:389/dc=lework,dc=com</url>
<username>CN=Administrator,CN=Users,DC=lework,DC=com</username>
<password>Admin123</password>
<authentication>SIMPLE</authentication>
<referral>IGNORE</referral>
<derefAliases>NEVER</derefAliases>
<version>VERSION_3</version>
<pageSize>1000</pageSize>
<factory>com.sun.jndi.ldap.LdapCtxFactory</factory>
<tlsActivated>false</tlsActivated>
</ldapConnection>
<ldapConnection>
<name>openldap</name>
<url>ldap://127.0.0.1:389/dc=lework,dc=com</url>
<username>cn=Manager,dc=lework,dc=com</username>
<password>123456</password>
<authentication>SIMPLE</authentication>
<referral>THROW</referral>
<derefAliases>NEVER</derefAliases>
<version>VERSION_3</version>
<pageSize>-1</pageSize>
<factory>com.sun.jndi.ldap.LdapCtxFactory</factory>
<tlsActivated>false</tlsActivated>
</ldapConnection>
</connections>
<tasks>
<task>
<name>a-PeopleSyncTask</name>
<bean>org.lsc.beans.SimpleBean</bean>
<ldapSourceService>
<name>ad-source-service</name>
<connection reference="ad"/>
<baseDn>CN=Users,DC=lework,DC=com</baseDn>
<pivotAttributes>
<string>samAccountName</string>
</pivotAttributes>
<fetchedAttributes>
<string>description</string>
<string>cn</string>
<string>sn</string>
<string>givenName</string>
<string>mail</string>
<string>samAccountName</string>
<string>userPrincipalName</string>
</fetchedAttributes>
<getAllFilter>(&(objectClass=user)(!(cn=Administrator))(!(cn=Guest))(!(cn=DefaultAccount))(!(cn=krbtgt)))</getAllFilter>
<getOneFilter>(&(objectClass=user)(samAccountName={samAccountName}))</getOneFilter>
<cleanFilter>(&(objectClass=user)(samAccountName={uid}))</cleanFilter>
</ldapSourceService>
<ldapDestinationService>
<name>opends-dst-service</name>
<connection reference="openldap"/>
<baseDn>ou=People,dc=lework,dc=com</baseDn>
<pivotAttributes>
<string>uid</string>
</pivotAttributes>
<fetchedAttributes>
<string>description</string>
<string>cn</string>
<string>sn</string>
<string>userPassword</string>
<string>objectClass</string>
<string>uid</string>
<string>mail</string>
</fetchedAttributes>
<getAllFilter>(objectClass=inetorgperson)</getAllFilter>
<getOneFilter>(&(objectClass=inetorgperson)(uid={samAccountName}))</getOneFilter>
</ldapDestinationService>
<propertiesBasedSyncOptions>
<mainIdentifier>"uid=" + srcBean.getDatasetFirstValueById("samAccountName") + ",ou=People,dc=lework,dc=com"</mainIdentifier>
<defaultDelimiter>;</defaultDelimiter>
<defaultPolicy>FORCE</defaultPolicy>
<conditions>
<create>true</create>
<update>true</update>
<delete>false</delete>
<changeId>true</changeId>
</conditions>
<dataset>
<name>objectClass</name>
<policy>KEEP</policy>
<createValues>
<string>"organizationalPerson"</string>
<string>"inetOrgPerson"</string>
<string>"person"</string>
<string>"top"</string>
</createValues>
</dataset>
<dataset>
<name>description</name>
<policy>FORCE</policy>
<forceValues>
<string>js:srcBean.getDatasetFirstValueById("cn").toUpperCase() + " (" + srcBean.getDatasetFirstValueById("userPrincipalName") + ")"</string>
</forceValues>
</dataset>
<dataset>
<name>userPassword</name>
<policy>KEEP</policy>
<createValues>
<string>js:"{SASL}" + srcBean.getDatasetFirstValueById("userPrincipalName")</string>
</createValues>
</dataset>
<dataset>
<name>sn</name>
<policy>FORCE</policy>
<createValues>
<string>js:srcBean.getDatasetFirstValueById("cn")</string>
</createValues>
</dataset>
<dataset>
<name>uid</name>
<policy>KEEP</policy>
<createValues>
<string>js:srcBean.getDatasetFirstValueById("cn")</string>
</createValues>
</dataset>
<dataset>
<name>mail</name>
<policy>FORCE</policy>
<forceValues>
<string>js:srcBean.getDatasetFirstValueById("mail")</string>
</forceValues>
</dataset>
</propertiesBasedSyncOptions>
</task>
<task>
<name>b-GroupSyncTask</name>
<bean>org.lsc.beans.SimpleBean</bean>
<ldapSourceService>
<name>ad-src-service</name>
<connection reference="ad"/>
<baseDn>CN=Users,DC=lework,DC=com</baseDn>
<pivotAttributes>
<string>cn</string>
</pivotAttributes>
<fetchedAttributes>
<string>cn</string>
<string>member</string>
<string>description</string>
</fetchedAttributes>
<getAllFilter>(&(objectClass=group)(member=*))</getAllFilter>
<getOneFilter>(&(objectClass=group)(cn={cn}))</getOneFilter>
<cleanFilter>(&(objectClass=group)(cn={cn}))</cleanFilter>
<interval>100</interval>
</ldapSourceService>
<ldapDestinationService>
<name>openldap-dst-service</name>
<connection reference="openldap"/>
<baseDn>ou=Group,DC=lework,DC=com</baseDn>
<pivotAttributes>
<string>cn</string>
</pivotAttributes>
<fetchedAttributes>
<string>cn</string>
<string>member</string>
<string>objectClass</string>
<string>description</string>
</fetchedAttributes>
<getAllFilter>(objectClass=groupOfNames)</getAllFilter>
<getOneFilter>(&(objectClass=groupOfNames)(cn={cn}))</getOneFilter>
</ldapDestinationService>
<propertiesBasedSyncOptions>
<mainIdentifier>"cn=" + javax.naming.ldap.Rdn.escapeValue(srcBean.getDatasetFirstValueById("cn")) + ",ou=Group,DC=lework,DC=com"</mainIdentifier>
<defaultDelimiter>;</defaultDelimiter>
<defaultPolicy>FORCE</defaultPolicy>
<conditions>
<create>true</create>
<update>true</update>
<delete>false</delete>
<changeId>true</changeId>
</conditions>
<dataset>
<name>objectClass</name>
<policy>FORCE</policy>
<forceValues>
<string>"groupOfNames"</string>
<string>"top"</string>
</forceValues>
<delimiter>$</delimiter>
</dataset>
<dataset>
<name>default</name>
<policy>FORCE</policy>
</dataset>
</propertiesBasedSyncOptions>
</task>
</tasks>
</lsc>
这里可以使用非ssl方式连接AD
执行同步
# 测试任务
/usr/bin/lsc -f /etc/lsc/ad2openldap -s all -c all -n
......
七月 25 11:43:20 - INFO - Starting sync for a-PeopleSyncTask
七月 25 11:43:22 - INFO - All entries: 4, to modify entries: 2, successfully modified entries: 0, errors: 0
七月 25 11:43:22 - INFO - Starting clean for a-PeopleSyncTask
七月 25 11:43:22 - INFO - All entries: 2, to modify entries: 0, successfully modified entries: 0, errors: 0
七月 25 11:43:22 - INFO - Starting sync for b-GroupSyncTask
七月 25 11:43:23 - INFO - All entries: 8, to modify entries: 8, successfully modified entries: 0, errors: 0
七月 25 11:43:23 - INFO - Starting clean for b-GroupSyncTask
七月 25 11:43:23 - ERROR - Empty or non existant destination (no IDs found)
# 执行同步
/usr/bin/lsc -f /etc/lsc/ad2openldap -s all -c all
......
七月 25 11:43:36 - INFO - Starting sync for a-PeopleSyncTask
七月 25 11:43:38 - INFO - # Adding new object uid=ad_test2,ou=People,dc=lework,dc=com for a-PeopleSyncTask
# Thu Jul 25 11:43:38 CST 2019
dn: uid=ad_test2,ou=People,dc=lework,dc=com
changetype: add
uid: ad_test2
userPassword: {SASL}ad_test2@lework.com
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: person
objectClass: top
description: AD_TEST2 (ad_test2@lework.com)
cn: ad_test2
sn: ad_test2
七月 25 11:43:38 - INFO - # Adding new object uid=ad_test1,ou=People,dc=lework,dc=com for a-PeopleSyncTask
# Thu Jul 25 11:43:38 CST 2019
dn: uid=ad_test1,ou=People,dc=lework,dc=com
changetype: add
uid: ad_test1
userPassword: {SASL}ad_test1@lework.com
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: person
objectClass: top
description: AD_TEST1 (ad_test1@lework.com)
cn: ad_test1
sn: ad_test1
七月 25 11:43:38 - INFO - All entries: 4, to modify entries: 2, successfully modified entries: 2, errors: 0
七月 25 11:43:38 - INFO - Starting clean for a-PeopleSyncTask
七月 25 11:43:38 - INFO - All entries: 4, to modify entries: 0, successfully modified entries: 0, errors: 0
七月 25 11:43:38 - INFO - Starting sync for b-GroupSyncTask
七月 25 11:43:39 - ERROR - Error while adding entry cn=ldapgroup2,ou=Group,DC=lework,DC=com in directory :javax.naming.NameAlreadyBoundException: [LDAP: error code 68 - Entry Already Exists]; remaining name 'cn=ldapgroup2,ou=Group'
七月 25 11:43:39 - ERROR - Error while synchronizing ID cn=ldapgroup2,ou=Group,DC=lework,DC=com: java.lang.Exception: Technical problem while applying modifications to the destination
# Thu Jul 25 11:43:39 CST 2019
dn: cn=ldapgroup2,ou=Group,DC=lework,DC=com
changetype: add
member: CN=ldapuser2,CN=Users,DC=lework,DC=com
objectClass: groupOfNames
objectClass: top
cn: ldapgroup2
七月 25 11:43:39 - INFO - # Adding new object cn=Denied RODC Password Replication Group,ou=Group,DC=lework,DC=com for b-GroupSyncTask
# Thu Jul 25 11:43:39 CST 2019
dn: cn=Denied RODC Password Replication Group,ou=Group,DC=lework,DC=com
changetype: add
member: CN=Read-only Domain Controllers,CN=Users,DC=lework,DC=com
member: CN=Group Policy Creator Owners,CN=Users,DC=lework,DC=com
member: CN=Domain Admins,CN=Users,DC=lework,DC=com
member: CN=Cert Publishers,CN=Users,DC=lework,DC=com
member: CN=Enterprise Admins,CN=Users,DC=lework,DC=com
member: CN=Schema Admins,CN=Users,DC=lework,DC=com
member: CN=Domain Controllers,CN=Users,DC=lework,DC=com
member: CN=krbtgt,CN=Users,DC=lework,DC=com
objectClass: groupOfNames
objectClass: top
description:: 5LiN5YWB6K645bCG5q2k57uE5Lit5oiQ5ZGY55qE5a+G56CB5aSN5Yi25Yiw5Z+f5Lit55qE5omA5pyJ5Y+q6K+75Z+f5o6n5Yi25Zmo
cn: Denied RODC Password Replication Group
七月 25 11:43:39 - INFO - # Adding new object cn=Schema Admins,ou=Group,DC=lework,DC=com for b-GroupSyncTask
# Thu Jul 25 11:43:39 CST 2019
dn: cn=Schema Admins,ou=Group,DC=lework,DC=com
changetype: add
member: CN=Administrator,CN=Users,DC=lework,DC=com
objectClass: groupOfNames
objectClass: top
description:: 5p625p6E55qE5oyH5a6a57O757uf566h55CG5ZGY
cn: Schema Admins
七月 25 11:43:39 - INFO - # Adding new object cn=Domain Admins,ou=Group,DC=lework,DC=com for b-GroupSyncTask
# Thu Jul 25 11:43:39 CST 2019
dn: cn=Domain Admins,ou=Group,DC=lework,DC=com
changetype: add
member: CN=Administrator,CN=Users,DC=lework,DC=com
objectClass: groupOfNames
objectClass: top
description:: 5oyH5a6a55qE5Z+f566h55CG5ZGY
cn: Domain Admins
七月 25 11:43:39 - INFO - # Adding new object cn=Enterprise Admins,ou=Group,DC=lework,DC=com for b-GroupSyncTask
# Thu Jul 25 11:43:39 CST 2019
dn: cn=Enterprise Admins,ou=Group,DC=lework,DC=com
changetype: add
member: CN=Administrator,CN=Users,DC=lework,DC=com
objectClass: groupOfNames
objectClass: top
description:: 5LyB5Lia55qE5oyH5a6a57O757uf566h55CG5ZGY
cn: Enterprise Admins
七月 25 11:43:39 - INFO - # Adding new object cn=Cert Publishers,ou=Group,DC=lework,DC=com for b-GroupSyncTask
# Thu Jul 25 11:43:39 CST 2019
dn: cn=Cert Publishers,ou=Group,DC=lework,DC=com
changetype: add
member: CN=WIN-V5SBNPSNFOM,OU=Domain Controllers,DC=lework,DC=com
objectClass: groupOfNames
objectClass: top
description:: 5q2k57uE55qE5oiQ5ZGY6KKr5YWB6K645Y+R5biD6K+B5Lmm5Yiw55uu5b2V
cn: Cert Publishers
七月 25 11:43:39 - ERROR - Error while adding entry cn=ldapgroup1,ou=Group,DC=lework,DC=com in directory :javax.naming.NameAlreadyBoundException: [LDAP: error code 68 - Entry Already Exists]; remaining name 'cn=ldapgroup1,ou=Group'
七月 25 11:43:39 - ERROR - Error while synchronizing ID cn=ldapgroup1,ou=Group,DC=lework,DC=com: java.lang.Exception: Technical problem while applying modifications to the destination
# Thu Jul 25 11:43:39 CST 2019
dn: cn=ldapgroup1,ou=Group,DC=lework,DC=com
changetype: add
member: CN=ldapuser1,CN=Users,DC=lework,DC=com
objectClass: groupOfNames
objectClass: top
cn: ldapgroup1
七月 25 11:43:39 - INFO - # Adding new object cn=Group Policy Creator Owners,ou=Group,DC=lework,DC=com for b-GroupSyncTask
# Thu Jul 25 11:43:39 CST 2019
dn: cn=Group Policy Creator Owners,ou=Group,DC=lework,DC=com
changetype: add
member: CN=Administrator,CN=Users,DC=lework,DC=com
objectClass: groupOfNames
objectClass: top
description:: 6L+Z5Liq57uE5Lit55qE5oiQ5ZGY5Y+v5Lul5L+u5pS55Z+f55qE57uE562W55Wl
cn: Group Policy Creator Owners
七月 25 11:43:39 - ERROR - All entries: 8, to modify entries: 8, successfully modified entries: 6, errors: 2
七月 25 11:43:39 - INFO - Starting clean for b-GroupSyncTask
七月 25 11:43:39 - INFO - All entries: 6, to modify entries: 0, successfully modified entries: 0, errors: 0
可以看到有2个用户,6个组成功同步到openldap中
AD是Active Directory的简写,中文称活动目录。活动目录(Active Directory)主要提供以下功能:
更多AD DS概述请查看微软技术文档,本文详细介绍AD DS的部署。
这里不描述系统安装过程
在需要安装AD域控制器的电脑上打开服务器管理器,点击添加角色和功能
打开添加角色和功能向导,点击下一步
安装类型选择基于角色或基于功能的安装,点击下一步
服务器选择从服务器池中选择服务器,再选中池中的本地服务器,点击下一步
服务器角色选择Active Directory域服务,会弹出添加Active Directory域服务所需的功能?,点击添加功能
点击下一步, 这里不需要选择
点击下一步
确认这里勾选如果需要,自动重新启动目标服务器,点击安装
Active Directory域服务角色安装完成,点关闭
运行AD DS(Active Directory域服务的简称)部署向导,打开本地服务器的服务器管理器,点击通知-将此服务器提升为域控制器
打开AD DS的部署向导,由于我们这里是部署新的AD控制器,所以部署配置选择添加新林,把根域名设置成lework.com,点击下一步
解释:
设置域密码,点击下一步
域控制器选项:
点击下一步
点击下一步
设置AD DS的数据库、日志文件和SYSVOL的位置,点击下一步
点击下一步
先决条件检查通过,点击安装,如果不通过请根据提示查看原因
正在进行自动部署,部署完成后会自动重启服务器
AD域控制器部署完成,打开服务器管理器-工具-Active Directory用户和计算机
就可以看到我们刚才部署好的域,这样一个完整的域就部署完成了
添加Active Directory 证书服务 角色
选择证书颁发机构
点击下一步进行安装
点击通知-配置目标服务器上的Active Directory 证书服务
点击下一步
勾选证书颁发机构,点击下一步
选择企业CA,点击下一步
选择根CA,点击下一步
选择创建新的私钥,点击下一步
指定CA的加密,默认即可.点击下一步
指定CA名称,点击下一步
指定有效期,这里设置为10年,点击下一步
指定CA数据库的位置,默认即可.点击下一步
确认证书的配置,点击配置.点击下一步
配置完成后,点击关闭页面
配置完成后,重启下服务器
在证书颁发机构中可以看到给域控颁发的证书
运行–>ldp.exe
host: WIN-V5SBNPSNFOM.lework.com port: 389
conn:LDAP:\\WIN-V5SBNPSNFOM.lework.com:389
host: WIN-V5SBNPSNFOM.lework.com port: 636
conn:LDAPS:\\WIN-V5SBNPSNFOM.lework.com:636
SSL 勾选上
在Active Directory服务器上执行以下命令来导出证书,供客户端连接使用
C:\Users\Administrator>certutil -ca.cert client.crt
CA 证书[0]: 3 -- 有效
CA 证书[0]:
-----BEGIN CERTIFICATE-----
MIIDfTCCAmWgAwIBAgIQKb58EV2zDLBAbvMySV/voDANBgkqhkiG9w0BAQsFADBR
MRMwEQYKCZImiZPyLGQBGRYDY29tMRYwFAYKCZImiZPyLGQBGRYGbGV3b3JrMSIw
IAYDVQQDExlsZXdvcmstV0lOLVY1U0JOUFNORk9NLUNBMB4XDTE5MDcyNDEwMjEw
NloXDTI5MDcyNDEwMzEwNlowUTETMBEGCgmSJomT8ixkARkWA2NvbTEWMBQGCgmS
JomT8ixkARkWBmxld29yazEiMCAGA1UEAxMZbGV3b3JrLVdJTi1WNVNCTlBTTkZP
TS1DQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANbilH1FFCE8UH/Y
ye8E0jMeDqjIEtAowvmu2yKbU+adKUJHo+gMYaL/3dXjFFI5Tr++WC/QROIbVAub
RzCZudGFQ2OKbr/yJ3mt6adB/VmdmGljX+2c1hmRHZcnuMyjnx7J/xqwkBlWxMpp
uP58VoaSJxQtUr/aO9dR53NsAa3pDcKYKfgWtNpCCa43YtY2x2pznpe4OOmQ1ufs
JENjJwA1e73Uq+TxKRKRRsE92SVxefbgSsOzO8Pg4Hyk1B2pIx267eYQFMngHlq2
ojd003HsMBtGU68F3IZRpyX+njpb28PANOL1MgVIRCT5HpddtV6R0Uvj84mBp0q0
6CwPWA8CAwEAAaNRME8wCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
VR0OBBYEFNMUY0FWH8vE5hsr5ZD9hrGF46rQMBAGCSsGAQQBgjcVAQQDAgEAMA0G
CSqGSIb3DQEBCwUAA4IBAQCj3EgCh4O7AutmMZE0/3UjOpz2o+GVIpym9V9JJGQw
z3rmmKtFO7G//YjjEN+bBmiDTUrmXTzar7RK8Vu2mLs+XqZipEE/GmcmdraZjQQD
2u3QZjKWFnLom1IIArbeIw9Mq6ZEr2cxsKI+biIg5YTpGjggyRrAHdFIdOInFYol
Zj50okNMZ+D7NJ83GupFCfFT7p4Glh2zL89a9u5qae9WE95y1G8fU30linQbCed2
ddCWWwU1+Jn5eEm0cAX5ogrY+UwqiYYBegWYLcxpndl/xLTGBYx7o7Sk2VMpHFO4
mPfPzpZ22rgS+Cvd7+S3nAvb22ygg1L+jMF63z8SFIP/
-----END CERTIFICATE-----
CertUtil: -ca.cert 命令成功完成。
使用SSL 配置OpenLDAP以进行安全通信。在此设置中,LDAP客户端通信通过安全端口636而不是非安全端口389进行。
在Multi-Master复制中,两个或多个服务器充当主服务器,所有这些服务器对LDAP目录中的任何更改都具有权威性。来自客户端的查询将在replication的帮助下分布在多个服务器上。