On 27/06/2022 15:16, Rob Crittenden wrote:
lejeczek via FreeIPA-users wrote:

On 03/06/2019 05:19, Alexander Bokovoy via FreeIPA-users wrote:
On Mon, 03 Jun 2019, Patrick Spinler via FreeIPA-users wrote:
Hi,

I'm setting up an openvpn server and I'd like to use our already
existing FreeIPA CA to issue user keys/certs for openvpn's use. Since
our OpenVPN box is a freeipa client, I thought it'd be nice to use
certmonger to issue and keep up to date these certs.

Ergo, I've created a certificate profile:

pat@apex-freeipa ~$ ipa certprofile-show --all OpenVPNUserCert
  dn: cn=OpenVPNUserCert,cn=certprofiles,cn=ca,dc=int,dc=apexmw,dc=com
  Profile ID: OpenVPNUserCert
  Profile description: OpenVPN User Certificates
  Store issued certificates: FALSE
  objectclass: ipacertprofile, top

And also a CA acl.   For experimentation (and working vs our test
freeipa) I've left this as wide open as I can:

[pat@apex-freeipa ~]$ ipa caacl-show --all OpenVPN_User_Certificate_ACL
  dn:
ipaUniqueID=6dde33a6-7849-11e9-aa05-525400b52c7b,cn=caacls,cn=ca,dc=int,dc=apexmw,dc=com

  ACL name: OpenVPN_User_Certificate_ACL
  Enabled: TRUE
  CA category: all
  Profile category: all
  User category: all
  Host category: all
  Service category: all
  ipauniqueid: 6dde33a6-7849-11e9-aa05-525400b52c7b
  objectclass: ipaassociation, ipacaacl

Then, on my openvpn server, I ask for a cert for use for one of my
users (myself, in this case):

root@apex-openvpn:~# ipa-getcert request -f
/etc/openvpn/client/pat.crt -k /etc/openvpn/client/pat.key -r -N
'CN=pat,O=INT.APEXMW.COM' -K pat -g 4096 --profile OpenVPNUserCert
New signing request "20190603014016" added.


But, it fails due to an access err vs the 'userCertificate' attribute
of my account:

root@apex-openvpn:~# ipa-getcert list
(...snippy snip excess...)
Request ID '20190603014016':
     status: CA_REJECTED
     ca-error: Server at https://apex-freeipa.int.apexmw.com/ipa/xml
denied our request, giving up: 2100 (RPC failed at server.
Insufficient access: Insufficient 'write' privilege to the
'userCertificate' attribute of entry
'uid=pat,cn=users,cn=accounts,dc=int,dc=apexmw,dc=com'.).
     stuck: yes
     key pair storage: type=FILE,location='/etc/openvpn/client/pat.key'
     certificate: type=FILE,location='/etc/openvpn/client/pat.crt'
     CA: IPA
     issuer:
     subject:
     expires: unknown
     pre-save command:
     post-save command:
     track: yes
     auto-renew: yes

If I look at the dirsrv log, here's the accesses I see for this request
(trimmed off the date/time to make the lines a _little_ shorter):

root@apex-freeipa slapd-INT-APEXMW-COM# grep conn=178 access | cut
-d' ' -f3-
conn=178 fd=114 slot=114 connection from 10.10.200.1 to 10.10.200.1
conn=178 op=0 BIND dn="" method=sasl version=3 mech=GSS-SPNEGO
conn=178 op=0 RESULT err=0 tag=97 nentries=0 etime=0.0025554208
dn="fqdn=apex-openvpn.int.apexmw.com,cn=computers,cn=accounts,dc=int,dc=apexmw,dc=com"

conn=178 op=1 SRCH base="cn=ipaconfig,cn=etc,dc=int,dc=apexmw,dc=com"
scope=0 filter="(objectClass=*)" attrs=ALL
conn=178 op=1 RESULT err=0 tag=101 nentries=1 etime=0.0001319554
conn=178 op=2 SRCH
base="cn=masters,cn=ipa,cn=etc,dc=int,dc=apexmw,dc=com" scope=2
filter="(&(objectClass=ipaConfigObject)(cn=CA))" attrs=ALL
conn=178 op=2 RESULT err=0 tag=101 nentries=1 etime=0.0000979573
conn=178 op=3 SRCH
base="cn=masters,cn=ipa,cn=etc,dc=int,dc=apexmw,dc=com" scope=2
filter="(&(objectClass=ipaConfigObject)(cn=CA))" attrs=ALL
conn=178 op=3 RESULT err=0 tag=101 nentries=1 etime=0.0000736730
conn=178 op=4 SRCH base="cn=cas,cn=ca,dc=int,dc=apexmw,dc=com"
scope=2 filter="(&(objectClass=ipaca)(cn=ipa))" attrs=""
conn=178 op=4 RESULT err=0 tag=101 nentries=1 etime=0.0000499142
conn=178 op=5 SRCH base="cn=ipa,cn=cas,cn=ca,dc=int,dc=apexmw,dc=com"
scope=0 filter="(objectClass=*)" attrs="ipaCaId ipaCaSubjectDN cn
ipaCaIssuerDN description"
conn=178 op=5 RESULT err=0 tag=101 nentries=1 etime=0.0000482726
conn=178 op=6 SRCH
base="cn=apex-freeipa.int.apexmw.com,cn=masters,cn=ipa,cn=etc,dc=int,dc=apexmw,dc=com"
scope=2
filter="(&(objectClass=ipaConfigObject)(ipaConfigString=enabledService)(cn=CA))"
attrs=ALL
conn=178 op=6 RESULT err=0 tag=101 nentries=1 etime=0.0000950646 notes=U
conn=178 op=7 SRCH base="cn=accounts,dc=int,dc=apexmw,dc=com" scope=2
filter="(&(objectClass=krbprincipalaux)([email protected]))"
attrs=ALL
conn=178 op=7 RESULT err=0 tag=101 nentries=1 etime=0.0002747849
conn=178 op=8 EXT oid="1.3.6.1.4.1.4203.1.11.3" name="whoami-plugin"
conn=178 op=8 RESULT err=0 tag=120 nentries=0 etime=0.0000135034
conn=178 op=9 SRCH base="cn=request certificate ignore
caacl,cn=virtual operations,cn=etc,dc=int,dc=apexmw,dc=com" scope=0
filter="(objectClass=*)" attrs="objectClass"
conn=178 op=9 RESULT err=0 tag=101 nentries=1 etime=0.0000932668 -
entryLevelRights: none
conn=178 op=10 SRCH
base="uid=pat,cn=users,cn=accounts,dc=int,dc=apexmw,dc=com" scope=0
filter="(objectClass=*)" attrs="distinguishedName"
conn=178 op=10 RESULT err=0 tag=101 nentries=1 etime=0.0000640289
conn=178 op=11 SRCH
base="uid=pat,cn=users,cn=accounts,dc=int,dc=apexmw,dc=com" scope=0
filter="(objectClass=*)" attrs="telephoneNumber ipaSshPubKey uid
krbCanonicalName ipatokenRadiusUserName ipaUserAuthType
krbPrincipalExpiration homeDirectory nsAccountLock
usercertificate;binary title loginShell uidNumber mail ipaCertMapData
memberOf memberofindirect krbPrincipalName givenName gidNumber sn ou
userClass ipatokenRadiusConfigLink"
conn=178 op=11 RESULT err=0 tag=101 nentries=1 etime=0.0001401737
conn=178 op=12 SRCH base="dc=int,dc=apexmw,dc=com" scope=2
filter="(|(member=uid=pat,cn=users,cn=accounts,dc=int,dc=apexmw,dc=com)(memberUser=uid=pat,cn=users,cn=accounts,dc=int,dc=apexmw,dc=com)(memberHost=uid=pat,cn=users,cn=accounts,dc=int,dc=apexmw,dc=com))"
attrs=""
conn=178 op=12 RESULT err=0 tag=101 nentries=7 etime=0.0001492344
notes=P pr_idx=0 pr_cookie=-1
conn=178 op=13 SRCH
base="uid=pat,cn=users,cn=accounts,dc=int,dc=apexmw,dc=com" scope=0
filter="(userPassword=*)" attrs="userPassword"
conn=178 op=13 RESULT err=0 tag=101 nentries=1 etime=0.0000524838
conn=178 op=14 SRCH
base="uid=pat,cn=users,cn=accounts,dc=int,dc=apexmw,dc=com" scope=0
filter="(krbPrincipalKey=*)" attrs="krbPrincipalKey"
conn=178 op=14 RESULT err=0 tag=101 nentries=1 etime=0.0000597589
conn=178 op=15 SRCH
base="ipaUniqueID=80b23b30-6a0c-11e9-baa3-525400b52c7b,cn=sudorules,cn=sudo,dc=int,dc=apexmw,dc=com"
scope=0 filter="(objectClass=*)" attrs="cn"
conn=178 op=15 RESULT err=0 tag=101 nentries=1 etime=0.0000379744
conn=178 op=16 SRCH
base="ipaUniqueID=5fb3a640-705a-11e9-aa05-525400b52c7b,cn=hbac,dc=int,dc=apexmw,dc=com"
scope=0 filter="(objectClass=*)" attrs="cn"
conn=178 op=16 RESULT err=0 tag=101 nentries=1 etime=0.0000337904
conn=178 op=17 SRCH base="cn=caacls,cn=ca,dc=int,dc=apexmw,dc=com"
scope=1
filter="(&(objectClass=ipaassociation)(objectClass=ipacaacl))"
attrs="serviceCategory cn ipaMemberCertProfile ipaMemberCa
ipaCertProfileCategory memberUser userCategory hostCategory
memberHost ipaEnabledFlag ipaCaCategory memberService description"
conn=178 op=17 RESULT err=0 tag=101 nentries=2 etime=0.0001647058
conn=178 op=18 EXT oid="1.3.6.1.4.1.4203.1.11.3" name="whoami-plugin"
conn=178 op=18 RESULT err=0 tag=120 nentries=0 etime=0.0000138321
conn=178 op=19 SRCH
base="uid=pat,cn=users,cn=accounts,dc=int,dc=apexmw,dc=com" scope=0
filter="(objectClass=*)" attrs="userCertificate"
conn=178 op=19 RESULT err=0 tag=101 nentries=1 etime=0.0001475052 -
entryLevelRights: none
conn=178 op=20 UNBIND
conn=178 op=20 fd=114 closed - U1

To begin with, I note that this session does a BIND with 'dn=""', right
at the beginning, it's essentially an anonymous bind, yah?
No, it is not. BIND operation may be multi-round and actual result is
not known until all rounds passed through. In your cases, SASL
GSS-SPNEGO is in use, so on the first round you get the bound identity:

conn=178 op=0 BIND dn="" method=sasl version=3 mech=GSS-SPNEGO
conn=178 op=0 RESULT err=0 tag=97 nentries=0 etime=0.0025554208
dn="fqdn=apex-openvpn.int.apexmw.com,cn=computers,cn=accounts,dc=int,dc=apexmw,dc=com"


E.g. all connection was done using host keytab of that machine
(apex-openvpn.int....). This is how certmonger works -- it uses a host
keytab of the machine it runs on.

That operation near the end, here:

op=17 SRCH base="cn=caacls,cn=ca,dc=int,dc=apexmw,dc=com" scope=1
filter="(&(objectClass=ipaassociation)(objectClass=ipacaacl))"

seems like it might be kinda key.  and indeed, if I attempt to run this
by hand as an anonymous bind, I get no results:

root@apex-freeipa slapd-INT-APEXMW-COM# ldapsearch -x -h localhost -b
dc=int,dc=apexmw,dc=com -s sub
"(|(objectClass=ipaassociation)(objectClass=ipacaacl))"
# extended LDIF
#
# LDAPv3
# base <dc=int,dc=apexmw,dc=com> with scope subtree
# filter: (|(objectClass=ipaassociation)(objectClass=ipacaacl))
# requesting: ALL
#

# search result
search: 2
result: 0 Success

# numResponses: 1

It's only if I run this as an _authenticated_ bind, that I can find
my ACL:

root@apex-freeipa slapd-INT-APEXMW-COM# ldapsearch -x -D
"cn=Directory Manager" -W -h localhost -b dc=int,dc=apexmw,dc=com -s
sub "(&(objectClass=ipaassociation)(objectClass=ipacaacl))" cn
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=int,dc=apexmw,dc=com> with scope subtree
# filter: (&(objectClass=ipaassociation)(objectClass=ipacaacl))
# requesting: cn
#

# c98b740c-6903-11e9-ad1b-525400b52c7b, caacls, ca, int.apexmw.com
dn:
ipaUniqueID=c98b740c-6903-11e9-ad1b-525400b52c7b,cn=caacls,cn=ca,dc=int,dc

=apexmw,dc=com
cn: hosts_services_caIPAserviceCert

# 6dde33a6-7849-11e9-aa05-525400b52c7b, caacls, ca, int.apexmw.com
dn:
ipaUniqueID=6dde33a6-7849-11e9-aa05-525400b52c7b,cn=caacls,cn=ca,dc=int,dc

=apexmw,dc=com
cn: OpenVPN_User_Certificate_ACL

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

Is this (using certmonger to auto-issue signed certs/keys for my
openvpn users) going to be essentially impossible to do, here? Do I
need to go a more traditional route of creating a seperate
keystore/certdb, issuing a CSR, and feeding that to FreeIPA to sign?
You'd need to create an ACL that would allow a host identity that
certmonger uses to have write rights to the userCertificate attribute of
the target user. You are already successfully passed CA ACL check
because the framework tried to see if you have rights to actually write
the resulting certificate (public cert) to the userCertficiate attribute
of the target entry, so it was not a question whether you can issue
(yes, you can) but whether you can store the cert (you cannot).

A way to create that would be by utilizing permissions/roles system of
FreeIPA.

Something like this:

ipa permission-add write-user-certificate-permission \
    --right=write --attrs=userCertificate --type=user

ipa privilege-add write-user-certificate-privilege
ipa privilege-add-permission write-user-certificate-privilege \
    --permissions=write-user-certificate-permission

ipa role-add user-certificate-issuer
ipa role-add-privilege user-certificate-issuer \
    --privileges=write-user-certificate-privilege
ipa role-add-member user-certificate-issuer \
    --hosts=apex-openvpn



I'm curious - what do you guys do/advise would be best "logistics" for
user certs - would you have separate user certs per-service or for
perhaps, for sake of easing the burden of it all, just single cert for a
user no matter the services?
Are we still talking VPN? I mean for that having a single purpose cert
could be useful since a VPN is generally launched separately from a
typical user use case. But otherwise I think it would be a drag for
user's to have to pick from a list in the browser as they switch
services. It could be a high overhead method of access control. High
because the more certs, the more chances of renewal problems,
revocation, CRL management, etc.

rob

That is was thinking - even if I did not mean each "http service/site" separately - that for some/any-thing that can use 'pam', so each DB, say mariadb, pgsql, etc, even if one-user-cert for all 'http', it would be not worth the "benefits" to manage user-cert for each such 'service'.

thanks, L.
_______________________________________________
FreeIPA-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/[email protected]
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to