Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure Anonymous PKINIT on server install #62

Closed
wants to merge 1 commit into from

Conversation

simo5
Copy link
Contributor

@simo5 simo5 commented Sep 6, 2016

Allow anonymous pkinit to be used so that unenrolled hosts can perform FAST
authentication (necessary for 2FA for example) using an anonymous krbtgt
obtained via Pkinit.

Signed-off-by: Simo Sorce simo@redhat.com

@simo5
Copy link
Contributor Author

simo5 commented Sep 6, 2016

Note, I haven't looked into the upgrade of an existing server, so just posting it here for an initial review, and also for someone to pick it up if I can't finish the work on the upgrade path.

@abbra @frasertweedale please take a look

@simo5 simo5 force-pushed the kdc-pkinit branch 5 times, most recently from 0fdf136 to 973fe14 Compare September 8, 2016 18:17
@abbra
Copy link
Contributor

abbra commented Sep 9, 2016

Thanks. Looks good. I'll work on upgrade next week and will do actual testing.

@martbab
Copy link
Contributor

martbab commented Sep 21, 2016

Regarding requesting certificate for krbtgt, we plan to fix cert-request in a more systematic manner to allow requesting certificate for any principal in IPA realm (see https://fedorahosted.org/freeipa/ticket/6295) so hopefully the cert-request fixes would not be needed eventually.

As a side question is the separate profile needed due to some custom extensions required for PKINIT certificate?

@abbra
Copy link
Contributor

abbra commented Sep 21, 2016

As a side question is the separate profile needed due to some custom extensions required for PKINIT certificate?
yes, we don't want to allow everyone to issue certificates with PKINIT extensions, they only should be done for KDC cert.

@martbab
Copy link
Contributor

martbab commented Sep 21, 2016

I thought so, it would be nice to have this mentioned somewhere, e.g. in profile description so that the future selves will know why this is needed.

@abbra
Copy link
Contributor

abbra commented Sep 21, 2016

Yes, we need to create a design page for PKINIT support. I'll make sure it is done.

@martbab
Copy link
Contributor

martbab commented Sep 21, 2016

Thank you

@splashx
Copy link

splashx commented Nov 21, 2016

For those running 4.4.2, is there a workaround to enable ANONYMOUS support?
We are not yet using client certs, we actually use a third-party OTP provider via RADIUS, so this is kind of a deal breaker :(

@simo5
Copy link
Contributor Author

simo5 commented Nov 21, 2016

@splashx you would have to manually configure each KDC and give them certs, it is doable.

@splashx
Copy link

splashx commented Nov 28, 2016

@simo5 done, however not successfully. It's not really my first time on the pkinit rodeo, so I'm wondering if FreeIPA's got something on top. I've got one freeipa instance for testing purposes, so not fussing with several servers. For debug purposes, I have done:

/etc/kdc.conf

[kdcdefaults]
 kdc_ports = 88
 kdc_tcp_ports = 88
+ restrict_anonymous_to_tgt = true

[realms]
 REALM.EU = {
  master_key_type = aes256-cts
  max_life = 7d
  max_renewable_life = 14d
  acl_file = /etc/krb5kdc/kadm5.acl
  dict_file = /usr/share/dict/words
  default_principal_flags = +preauth
;  admin_keytab = /etc/krb5kdc/kadm5.keytab
+   pkinit_identity = FILE:/var/lib/krb5kdc/kdc.pem,/var/lib/krb5kdc/kdckey.pem  
+   pkinit_eku_checking = none
 }

The anonymous user (created manually first with-rankey, modified with -requires_preauth and then later with purgekeys -all WELLKNOWN/ANONYMOUS@REALM.EU) looks like this:

root@ipa01:/var/lib/krb5kdc# kadmin.local -x ipa-setup-override-restrictions
Authenticating as principal admin/admin@REALM.EU with password.
kadmin.local:  getprinc WELLKNOWN/ANONYMOUS@REALM.EU
Principal: WELLKNOWN/ANONYMOUS@REALM.EU
Expiration date: [never]
Last password change: Mon Nov 28 12:46:41 UTC 2016
Password expiration date: [none]
Maximum ticket life: 1 day 00:00:00
Maximum renewable life: 7 days 00:00:00
Last modified: Mon Nov 28 16:04:32 UTC 2016 (admin/admin@REALM.EU)
Last successful authentication: [never]
Last failed authentication: [never]
Failed password attempts: 0
Number of keys: 0
MKey: vno 1
Attributes:
Policy: [none]

I made sure the certificate's common name matches the fqdn, but still getting on the client side:

root@ubuntu:~# KRB5_TRACE=/dev/stdout kinit -n
[10593] 1480350802.381306: Getting initial credentials for WELLKNOWN/ANONYMOUS@REALM.EU
[10593] 1480350802.384075: Sending request (178 bytes) to REALM.EU
[10593] 1480350802.433623: Retrying AS request with master KDC
[10593] 1480350802.434688: Getting initial credentials for WELLKNOWN/ANONYMOUS@REALM.EU
[10593] 1480350802.435476: Sending request (178 bytes) to REALM.EU (master)
[10593] 1480350802.436191: Resolving hostname kdc.domain.eu
[10593] 1480350802.462072: Sending initial UDP request to dgram 10.235.2.25:88
[10593] 1480350803.465087: Resolving hostname kdc.domain.eu
[10593] 1480350803.489656: Sending initial UDP request to dgram 10.235.2.25:750
[10593] 1480350804.491058: Initiating TCP connection to stream 10.235.2.25:88
[10593] 1480350804.515736: Sending TCP request to stream 10.235.2.25:88
[10593] 1480350804.547579: Received answer (269 bytes) from stream 10.235.2.25:88
[10593] 1480350804.547663: Received error from KDC: -1765328359/Additional pre-authentication required
[10593] 1480350804.547708: Processing preauth types: 16, 15, 14, 136, 147, 133
[10593] 1480350804.547713: Received cookie: MIT
[10593] 1480350804.547744: Preauth module pkinit (147) (info) returned: 0/Success
[10593] 1480350804.547758: PKINIT client has no configured identity; giving up
[10593] 1480350804.547765: Preauth module pkinit (16) (real) returned: 22/Invalid argument
[10593] 1480350804.547776: PKINIT client has no configured identity; giving up
[10593] 1480350804.547782: Preauth module pkinit (14) (real) returned: 22/Invalid argument
[10593] 1480350804.547793: PKINIT client has no configured identity; giving up
[10593] 1480350804.547798: Preauth module pkinit (14) (real) returned: 22/Invalid argument
kinit: Invalid argument while getting initial credentials
root@ubuntu:~# 

Any thoughts would be helpful.

Thanks in advance

@simo5
Copy link
Contributor Author

simo5 commented Nov 28, 2016

@splashx we are starting to pollute this PR here now. Please provide KDC logs on the user's mailing list and let's proceed there.

@simo5
Copy link
Contributor Author

simo5 commented Dec 1, 2016

@abbra this code needs rebase and I need it as dependency for solving ticket #5959, did you do any work on this ? If not I'll rebase tomorrow.

@abbra
Copy link
Contributor

abbra commented Dec 2, 2016

@simo5 I did a rebase a while a go and maintain it rebased against the master. I'll submit a new PR with the rebase.

@abbra
Copy link
Contributor

abbra commented Dec 2, 2016

@simo5 https://github.com/abbra/freeipa/tree/kdc-pkinit can be used for rebase of this PR

@simo5
Copy link
Contributor Author

simo5 commented Dec 2, 2016

Should I push your branch over my PR ?

@abbra
Copy link
Contributor

abbra commented Dec 2, 2016

Up to you. We can either resync yours or switch over to mine. I need to merge updater changes too before submitting it upstream, though.

@simo5
Copy link
Contributor Author

simo5 commented Dec 2, 2016 via email

@simo5
Copy link
Contributor Author

simo5 commented Dec 6, 2016

Rebased on latest master

@simo5
Copy link
Contributor Author

simo5 commented Dec 6, 2016

Rebasing this code is becoming a little difficult, @frasertweedale can you take a look and confirm the changes in cert.py are ok ?

martbab
martbab previously requested changes Dec 7, 2016
Copy link
Contributor

@martbab martbab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few small comments on the patch,

@@ -521,6 +521,11 @@ def install_check(installer):
dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin)

if options.pkinit_cert_files:
if not options.no_pkinit:
sys.exit("Cannot create KDC PKINIT certificate and use provided "
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please raise ScriptError here instead of hard exit. This is currently advised practice in installers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

# Restart krb after configurations have been changed
# Restart ds and krb after configurations have been changed
service.print_msg("Restarting the directory server")
ds.restart()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the DS restart necessary here? IIRC it is restarted at the end of update phase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure, I tink this came from a change @abbra made to forward port the patch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at it I think it should probably be a krb.restart(), but I did not have any issue installing, so perhaps it can simply go now, I'll wait for @abbra to comment if he recalls anything around this part.

@@ -216,6 +217,16 @@ def caacl_check(principal_type, principal, ca, profile_id):
)


def ca_kdc_check(ldap, basedn, hostname):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may simplify this check by several means: You can use server show/find hostname to check if it is really an IPA master, or you can call config_show and then check if the hostname is listed among IPA masters (hostname in result['ipa_master_server']. The latter is probably safer for your use-case as it queries the presence of KDC/HTTP/etc entries directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@@ -793,6 +838,9 @@ def execute(self, csr, all=False, raw=False, **kw):
api.Command['host_mod'](principal.hostname, **kwargs)
elif principal_type == USER:
api.Command['user_mod'](principal.username, **kwargs)
elif principal_type == KRBTGT:
root_logger.error("Profiles used to store cert should't be "
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use self.log.error here, according to logging best practices root_logger should never be used directly to emit messages so let's not spread the bad practices further.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I tried root_logger was the only way to use it IIRC.
I do not think this calss has a self.log

@martbab
Copy link
Contributor

martbab commented Dec 7, 2016

I have a few small comments on this PR, nothing serious.

@simo5 simo5 force-pushed the kdc-pkinit branch 2 times, most recently from 27e72f6 to 7bab75c Compare December 7, 2016 22:44
@simo5
Copy link
Contributor Author

simo5 commented Dec 7, 2016

@martbab your concerns should be addressed in this revision
I also started adding upgrade code, but it is still not fully tested.
In the process I locally get 2 pylint errors about the hostname property used on 2 out of 3 Principal() objects in cert.py, I am sorta baffled at why that is, but it is late here, so I decided to push the code and see if anyone has an idea.

@abbra
Copy link
Contributor

abbra commented Dec 8, 2016

@simo5 I tried to run the branch as an upgrade against Fedora 25 version (4.4.2-1.fc25) and it failed at first because I was running in SELinux enforcing:
Unexpected error - see /var/log/ipaupgrade.log for details:
DBusException: org.fedorahosted.certmonger.bad_arg: The parent of location "/var/kerberos/krb5kdc/kdc.crt" could not be accessed due to insufficient permissions.
The ipa-server-upgrade command failed. See /var/log/ipaupgrade.log for more information

Re-running ipa-server-upgrade with 'setenforce 0', I get different error:

2016-12-08T15:52:28Z ERROR IPA server upgrade failed: Inspect /var/log/ipaupgrade.log and run command ipa-server-upgrade manually.
2016-12-08T15:52:28Z DEBUG   File "/usr/lib/python2.7/site-packages/ipapython/admintool.py", line 172, in execute
    return_value = self.run()
  File "/usr/lib/python2.7/site-packages/ipaserver/install/ipa_server_upgrade.py", line 46, in run    server.upgrade()
  File "/usr/lib/python2.7/site-packages/ipaserver/install/server/upgrade.py", line 1820, in upgrade     upgrade_configuration()
  File "/usr/lib/python2.7/site-packages/ipaserver/install/server/upgrade.py", line 1755, in upgrade_configuration
    enable_anonymous_principal(krb)
  File "/usr/lib/python2.7/site-packages/ipaserver/install/server/upgrade.py", line 1498, in enable_anonymous_principal
    dn = DN(('krbprincipalname', princ_realm), krb.get_realm_suffix())
  File "/usr/lib/python2.7/site-packages/ipaserver/install/krbinstance.py", line 74, in get_realm_suffix
return DN(('cn', self.realm), ('cn', 'kerberos'), self.suffix)
  File "/usr/lib/python2.7/site-packages/ipapython/dn.py", line 1107, in __init__
self.rdns = self._rdns_from_sequence(args)
  File "/usr/lib/python2.7/site-packages/ipapython/dn.py", line 1148, in _rdns_from_sequence
rdn = self._rdns_from_value(item)
  File "/usr/lib/python2.7/site-packages/ipapython/dn.py", line 1141, in _rdns_from_value
% type(value))

2016-12-08T15:52:28Z DEBUG The ipa-server-upgrade command failed, exception: TypeError: must be str, unicode, tuple, Name, RDN or DN, got <type 'NoneType'> instead
2016-12-08T15:52:28Z ERROR Unexpected error - see /var/log/ipaupgrade.log for details:

TypeError: must be str, unicode, tuple, Name, RDN or DN, got <type 'NoneType'> instead

@@ -215,6 +216,11 @@ def caacl_check(principal_type, principal, ca, profile_id):
)
)

def ca_kdc_check(ldap, basedn, hostname):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You re-wrote the implementation but forgot to remove basedn param from signature, that's why you get pylint errors about no value for argument.

@martbab
Copy link
Contributor

martbab commented Dec 8, 2016

@simo5 I highlighted the code givin pylint issues, basically you forgot to update ca_kdc_check signature.

@simo5
Copy link
Contributor Author

simo5 commented Dec 8, 2016

@martbab sometimes you are blind to your own code ...

@simo5
Copy link
Contributor Author

simo5 commented Dec 8, 2016

@abbra I have an idea of what it might be

@simo5 simo5 force-pushed the kdc-pkinit branch 2 times, most recently from 641691c to 13caff8 Compare December 8, 2016 18:41
@simo5 simo5 dismissed martbab’s stale review December 8, 2016 18:43

All requeted changes should have been addressed

@simo5 simo5 force-pushed the kdc-pkinit branch 3 times, most recently from 5b28776 to eba8fa4 Compare December 9, 2016 13:12
@abbra
Copy link
Contributor

abbra commented Dec 11, 2016

Thanks @simo5. Except SELinux changes this PR is ready to be accepted.
TODO as separate pull requests:

  • SELinux policy needs to be updated to allow certmonger to write to /var/kerberos/krb5kdc/:
    allow certmonger_t krb5kdc_conf_t:dir { add_name write }
    allow certmonger_t krb5kdc_conf_t:file create;

  • For CA-less setup we need to add ipa-pkinit-manage to allow adding externally provided PKCS#12 package with KDC certificate after the installation

Also, to document the decisions we made when moving forward with this PR, anonymous PKINIT principal is created in all configurations. Its use for non-PKINIT case will be detailed in the privilege separation patchset:

  • for embedded CA, Anonymous PKINIT is used for password/2FA login FAST wrapping
  • If Anonymous PKINIT does not work (CA-less or external CA case with not configured PKINIT), Kerberos keytab with Anonymous principal will be used for FAST wrapping
  • Finally, if both of these cases don't work, privilege separation will degrade 2FA logon.

This allows us to fully utilize Anonymous Kerberos principal potential.

ACK.

@abbra abbra added the ack Pull Request approved, can be merged label Dec 11, 2016
princ_realm = krb.get_anonymous_principal_name()
dn = DN(('krbprincipalname', princ_realm), krb.get_realm_suffix())
try:
_ = api.Backend.ldap2.get_entry(dn) # pylint: disable=unused-variable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that instead of disabling the check, you could have renamed the variable to _entry - the unused variable regex is _.+ in IPA.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would argue that one does not even need to assign the result to a variable if it just checks for the entry's existence.

Allow anonymous pkinit to be used so that unenrolled hosts can perform FAST
authentication (necessary for 2FA for example) using an anonymous krbtgt
obtained via Pkinit.

https://fedorahosted.org/freeipa/ticket/5678

Signed-off-by: Simo Sorce <simo@redhat.com>
@HonzaCholasta HonzaCholasta added the pushed Pull Request has already been pushed label Dec 12, 2016
@HonzaCholasta
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ack Pull Request approved, can be merged pushed Pull Request has already been pushed
Projects
None yet
5 participants