Added vault access control.

New LDAP ACIs have been added to allow vault owners to manage the
vaults and to allow members to access the vaults. New CLIs have
been added to manage the owner and member list. The LDAP schema
has been updated as well.

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

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Endi S. Dewata
2014-10-17 12:05:34 -04:00
committed by Jan Cholasta
parent 5017726eba
commit bf6df3df9b
6 changed files with 226 additions and 33 deletions

92
API.txt
View File

@@ -5426,27 +5426,58 @@ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui
option: Str('service?') option: Str('service?')
option: Str('setattr*', cli_name='setattr', exclude='webui') option: Str('setattr*', cli_name='setattr', exclude='webui')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user?') option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: PrimaryKey('value', None, None) output: PrimaryKey('value', None, None)
command: vault_add_internal command: vault_add_internal
args: 1,10,3 args: 1,11,3
arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, required=True) arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, required=True)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False) option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False)
option: Bytes('ipavaultpublickey', attribute=True, cli_name='public_key', multivalue=False, required=False) option: Bytes('ipavaultpublickey', attribute=True, cli_name='public_key', multivalue=False, required=False)
option: Bytes('ipavaultsalt', attribute=True, cli_name='salt', multivalue=False, required=False) option: Bytes('ipavaultsalt', attribute=True, cli_name='salt', multivalue=False, required=False)
option: Str('ipavaulttype', attribute=True, autofill=True, cli_name='type', default=u'standard', multivalue=False, required=False) option: Str('ipavaulttype', attribute=True, autofill=True, cli_name='type', default=u'standard', multivalue=False, required=False)
option: Flag('no_members', autofill=True, default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('service?') option: Str('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user?') option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: PrimaryKey('value', None, None) output: PrimaryKey('value', None, None)
command: vault_add_member
args: 1,9,3
arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
option: Flag('no_members', autofill=True, default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('service?')
option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users', csv=True)
option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui')
output: Output('completed', <type 'int'>, None)
output: Output('failed', <type 'dict'>, None)
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
command: vault_add_owner
args: 1,9,3
arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
option: Flag('no_members', autofill=True, default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('service?')
option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users', csv=True)
option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui')
output: Output('completed', <type 'int'>, None)
output: Output('failed', <type 'dict'>, None)
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
command: vault_archive command: vault_archive
args: 1,10,3 args: 1,10,3
arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
@@ -5458,7 +5489,7 @@ option: Str('password_file?', cli_name='password_file')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('service?') option: Str('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user?') option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
@@ -5472,7 +5503,7 @@ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui
option: Str('service?') option: Str('service?')
option: Bytes('session_key') option: Bytes('session_key')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user?') option: Str('username?', cli_name='user')
option: Bytes('vault_data') option: Bytes('vault_data')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
@@ -5484,32 +5515,33 @@ arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=True,
option: Flag('continue', autofill=True, cli_name='continue', default=False) option: Flag('continue', autofill=True, cli_name='continue', default=False)
option: Str('service?') option: Str('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user?') option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Output('result', <type 'dict'>, None) output: Output('result', <type 'dict'>, None)
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: ListOfPrimaryKeys('value', None, None) output: ListOfPrimaryKeys('value', None, None)
command: vault_find command: vault_find
args: 1,12,4 args: 1,13,4
arg: Str('criteria?', noextrawhitespace=False) arg: Str('criteria?', noextrawhitespace=False)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Str('cn', attribute=True, autofill=False, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=False) option: Str('cn', attribute=True, autofill=False, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=False)
option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False) option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
option: Str('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, query=True, required=False) option: Str('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, query=True, required=False)
option: Flag('no_members', autofill=True, default=False, exclude='webui')
option: Flag('pkey_only?', autofill=True, default=False) option: Flag('pkey_only?', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('service?') option: Str('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Int('sizelimit?', autofill=False, minvalue=0) option: Int('sizelimit?', autofill=False, minvalue=0)
option: Int('timelimit?', autofill=False, minvalue=0) option: Int('timelimit?', autofill=False, minvalue=0)
option: Str('user?') option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Output('count', <type 'int'>, None) output: Output('count', <type 'int'>, None)
output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None)) output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: Output('truncated', <type 'bool'>, None) output: Output('truncated', <type 'bool'>, None)
command: vault_mod command: vault_mod
args: 1,14,3 args: 1,15,3
arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
option: Str('addattr*', cli_name='addattr', exclude='webui') option: Str('addattr*', cli_name='addattr', exclude='webui')
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -5518,16 +5550,47 @@ option: Str('description', attribute=True, autofill=False, cli_name='desc', mult
option: Bytes('ipavaultpublickey', attribute=True, autofill=False, cli_name='public_key', multivalue=False, required=False) option: Bytes('ipavaultpublickey', attribute=True, autofill=False, cli_name='public_key', multivalue=False, required=False)
option: Bytes('ipavaultsalt', attribute=True, autofill=False, cli_name='salt', multivalue=False, required=False) option: Bytes('ipavaultsalt', attribute=True, autofill=False, cli_name='salt', multivalue=False, required=False)
option: Str('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, required=False) option: Str('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, required=False)
option: Flag('no_members', autofill=True, default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Flag('rights', autofill=True, default=False) option: Flag('rights', autofill=True, default=False)
option: Str('service?') option: Str('service?')
option: Str('setattr*', cli_name='setattr', exclude='webui') option: Str('setattr*', cli_name='setattr', exclude='webui')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user?') option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: PrimaryKey('value', None, None) output: PrimaryKey('value', None, None)
command: vault_remove_member
args: 1,9,3
arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
option: Flag('no_members', autofill=True, default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('service?')
option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users', csv=True)
option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui')
output: Output('completed', <type 'int'>, None)
output: Output('failed', <type 'dict'>, None)
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
command: vault_remove_owner
args: 1,9,3
arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
option: Flag('no_members', autofill=True, default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('service?')
option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users', csv=True)
option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui')
output: Output('completed', <type 'int'>, None)
output: Output('failed', <type 'dict'>, None)
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
command: vault_retrieve command: vault_retrieve
args: 1,11,3 args: 1,11,3
arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
@@ -5540,7 +5603,7 @@ option: Str('private_key_file?', cli_name='private_key_file')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('service?') option: Str('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user?') option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
@@ -5553,20 +5616,21 @@ option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui
option: Str('service?') option: Str('service?')
option: Bytes('session_key') option: Bytes('session_key')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user?') option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: PrimaryKey('value', None, None) output: PrimaryKey('value', None, None)
command: vault_show command: vault_show
args: 1,7,3 args: 1,8,3
arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Flag('no_members', autofill=True, default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Flag('rights', autofill=True, default=False) option: Flag('rights', autofill=True, default=False)
option: Str('service?') option: Str('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user?') option: Str('username?', cli_name='user')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)

View File

@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
# # # #
######################################################## ########################################################
IPA_API_VERSION_MAJOR=2 IPA_API_VERSION_MAJOR=2
IPA_API_VERSION_MINOR=144 IPA_API_VERSION_MINOR=145
# Last change: ab - trusts: add support for one-way trust and switch to it by default # Last change: edewata - added vault access control

View File

@@ -82,4 +82,5 @@ objectClasses: (2.16.840.1.113730.3.8.12.24 NAME 'ipaPublicKeyObject' DESC 'Wrap
objectClasses: (2.16.840.1.113730.3.8.12.25 NAME 'ipaPrivateKeyObject' DESC 'Wrapped private keys' SUP top AUXILIARY MUST ( ipaPrivateKey $ ipaWrappingKey $ ipaWrappingMech ) X-ORIGIN 'IPA v4.1' ) objectClasses: (2.16.840.1.113730.3.8.12.25 NAME 'ipaPrivateKeyObject' DESC 'Wrapped private keys' SUP top AUXILIARY MUST ( ipaPrivateKey $ ipaWrappingKey $ ipaWrappingMech ) X-ORIGIN 'IPA v4.1' )
objectClasses: (2.16.840.1.113730.3.8.12.26 NAME 'ipaSecretKeyObject' DESC 'Wrapped secret keys' SUP top AUXILIARY MUST ( ipaSecretKey $ ipaWrappingKey $ ipaWrappingMech ) X-ORIGIN 'IPA v4.1' ) objectClasses: (2.16.840.1.113730.3.8.12.26 NAME 'ipaSecretKeyObject' DESC 'Wrapped secret keys' SUP top AUXILIARY MUST ( ipaSecretKey $ ipaWrappingKey $ ipaWrappingMech ) X-ORIGIN 'IPA v4.1' )
objectClasses: (2.16.840.1.113730.3.8.12.34 NAME 'ipaSecretKeyRefObject' DESC 'Indirect storage for encoded key material' SUP top AUXILIARY MUST ( ipaSecretKeyRef ) X-ORIGIN 'IPA v4.1' ) objectClasses: (2.16.840.1.113730.3.8.12.34 NAME 'ipaSecretKeyRefObject' DESC 'Indirect storage for encoded key material' SUP top AUXILIARY MUST ( ipaSecretKeyRef ) X-ORIGIN 'IPA v4.1' )
objectClasses: (2.16.840.1.113730.3.8.18.1.1 NAME 'ipaVault' DESC 'IPA vault' SUP top STRUCTURAL MUST ( cn ) MAY ( description $ ipaVaultType $ ipaVaultSalt $ ipaVaultPublicKey ) X-ORIGIN 'IPA v4.2' ) objectClasses: (2.16.840.1.113730.3.8.18.1.1 NAME 'ipaVault' DESC 'IPA vault' SUP top STRUCTURAL MUST ( cn ) MAY ( description $ ipaVaultType $ ipaVaultSalt $ ipaVaultPublicKey $ owner $ member ) X-ORIGIN 'IPA v4.2' )
objectClasses: (2.16.840.1.113730.3.8.18.1.2 NAME 'ipaVaultContainer' DESC 'IPA vault container' SUP top STRUCTURAL MUST ( cn ) MAY ( description $ owner ) X-ORIGIN 'IPA v4.2' )

View File

@@ -5,20 +5,27 @@ default: cn: kra
dn: cn=vaults,cn=kra,$SUFFIX dn: cn=vaults,cn=kra,$SUFFIX
default: objectClass: top default: objectClass: top
default: objectClass: nsContainer default: objectClass: ipaVaultContainer
default: cn: vaults default: cn: vaults
default: aci: (target="ldap:///cn=*,cn=users,cn=vaults,cn=kra,$SUFFIX")(version 3.0; acl "Allow users to create private container"; allow (add) userdn = "ldap:///uid=($$attr.cn),cn=users,cn=accounts,$SUFFIX";)
default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Container owners can manage vaults in the container"; allow(read, search, compare, add, delete) userattr="parent[1].owner#USERDN";)
default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect container owners can manage vaults in the container"; allow(read, search, compare, add, delete) userattr="parent[1].owner#GROUPDN";)
default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Vault members can access the vault"; allow(read, search, compare) userattr="member#USERDN";)
default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect vault members can access the vault"; allow(read, search, compare) userattr="member#GROUPDN";)
default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Vault owners can manage the vault"; allow(read, search, compare, write) userattr="owner#USERDN";)
default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect vault owners can manage the vault"; allow(read, search, compare, write) userattr="owner#GROUPDN";)
dn: cn=services,cn=vaults,cn=kra,$SUFFIX dn: cn=services,cn=vaults,cn=kra,$SUFFIX
default: objectClass: top default: objectClass: top
default: objectClass: nsContainer default: objectClass: ipaVaultContainer
default: cn: services default: cn: services
dn: cn=shared,cn=vaults,cn=kra,$SUFFIX dn: cn=shared,cn=vaults,cn=kra,$SUFFIX
default: objectClass: top default: objectClass: top
default: objectClass: nsContainer default: objectClass: ipaVaultContainer
default: cn: shared default: cn: shared
dn: cn=users,cn=vaults,cn=kra,$SUFFIX dn: cn=users,cn=vaults,cn=kra,$SUFFIX
default: objectClass: top default: objectClass: top
default: objectClass: nsContainer default: objectClass: ipaVaultContainer
default: cn: users default: cn: users

View File

@@ -42,7 +42,8 @@ from ipalib import output
from ipalib.crud import PKQuery, Retrieve, Update from ipalib.crud import PKQuery, Retrieve, Update
from ipalib.plugable import Registry from ipalib.plugable import Registry
from ipalib.plugins.baseldap import LDAPObject, LDAPCreate, LDAPDelete,\ from ipalib.plugins.baseldap import LDAPObject, LDAPCreate, LDAPDelete,\
LDAPSearch, LDAPUpdate, LDAPRetrieve, pkey_to_value LDAPSearch, LDAPUpdate, LDAPRetrieve, LDAPAddMember, LDAPRemoveMember,\
pkey_to_value
from ipalib.request import context from ipalib.request import context
from ipalib.plugins.user import split_principal from ipalib.plugins.user import split_principal
from ipalib import _, ngettext from ipalib import _, ngettext
@@ -195,6 +196,18 @@ EXAMPLES:
""") + _(""" """) + _("""
Retrieve data from asymmetric vault: Retrieve data from asymmetric vault:
ipa vault-retrieve <name> --out data.bin --private-key-file private.pem ipa vault-retrieve <name> --out data.bin --private-key-file private.pem
""") + _("""
Add a vault owner:
ipa vault-add-owner <name> --users <usernames>
""") + _("""
Delete a vault owner:
ipa vault-remove-owner <name> --users <usernames>
""") + _("""
Add a vault member:
ipa vault-add-member <name> --users <usernames>
""") + _("""
Delete a vault member:
ipa vault-remove-member <name> --users <usernames>
""") """)
register = Registry() register = Registry()
@@ -210,7 +223,8 @@ vault_options = (
doc=_('Shared vault'), doc=_('Shared vault'),
), ),
Str( Str(
'user?', 'username?',
cli_name='user',
doc=_('Username of the user vault'), doc=_('Username of the user vault'),
), ),
) )
@@ -234,12 +248,18 @@ class vault(LDAPObject):
'ipavaulttype', 'ipavaulttype',
'ipavaultsalt', 'ipavaultsalt',
'ipavaultpublickey', 'ipavaultpublickey',
'owner',
'member',
] ]
search_display_attributes = [ search_display_attributes = [
'cn', 'cn',
'description', 'description',
'ipavaulttype', 'ipavaulttype',
] ]
attribute_members = {
'owner': ['user', 'group'],
'member': ['user', 'group'],
}
label = _('Vaults') label = _('Vaults')
label_singular = _('Vault') label_singular = _('Vault')
@@ -282,6 +302,16 @@ class vault(LDAPObject):
doc=_('Vault public key'), doc=_('Vault public key'),
flags=['no_search'], flags=['no_search'],
), ),
Str(
'owner_user?',
label=_('Owner users'),
flags=['no_create', 'no_update', 'no_search'],
),
Str(
'owner_group?',
label=_('Owner groups'),
flags=['no_create', 'no_update', 'no_search'],
),
) )
def get_dn(self, *keys, **options): def get_dn(self, *keys, **options):
@@ -291,7 +321,7 @@ class vault(LDAPObject):
service = options.get('service') service = options.get('service')
shared = options.get('shared') shared = options.get('shared')
user = options.get('user') user = options.get('username')
count = 0 count = 0
if service: if service:
@@ -337,7 +367,7 @@ class vault(LDAPObject):
return DN(rdns, parent_dn) return DN(rdns, parent_dn)
def create_container(self, dn): def create_container(self, dn, owner_dn):
""" """
Creates vault container and its parents. Creates vault container and its parents.
""" """
@@ -354,8 +384,9 @@ class vault(LDAPObject):
entry = self.backend.make_entry( entry = self.backend.make_entry(
dn, dn,
{ {
'objectclass': ['nsContainer'], 'objectclass': ['ipaVaultContainer'],
'cn': rdn['cn'], 'cn': rdn['cn'],
'owner': [owner_dn],
}) })
# if entry can be added, return # if entry can be added, return
@@ -631,12 +662,21 @@ class vault_add_internal(LDAPCreate):
raise errors.InvocationError( raise errors.InvocationError(
format=_('KRA service is not enabled')) format=_('KRA service is not enabled'))
principal = getattr(context, 'principal')
(name, realm) = split_principal(principal)
if '/' in name:
owner_dn = self.api.Object.service.get_dn(name)
else:
owner_dn = self.api.Object.user.get_dn(name)
try: try:
parent_dn = DN(*dn[1:]) parent_dn = DN(*dn[1:])
self.obj.create_container(parent_dn) self.obj.create_container(parent_dn, owner_dn)
except errors.DuplicateEntry, e: except errors.DuplicateEntry, e:
pass pass
entry_attrs['owner'] = owner_dn
return dn return dn
@@ -687,6 +727,8 @@ class vault_find(LDAPSearch):
takes_options = LDAPSearch.takes_options + vault_options takes_options = LDAPSearch.takes_options + vault_options
has_output_params = LDAPSearch.has_output_params
msg_summary = ngettext( msg_summary = ngettext(
'%(count)d vault matched', '%(count)d vault matched',
'%(count)d vaults matched', '%(count)d vaults matched',
@@ -742,6 +784,8 @@ class vault_show(LDAPRetrieve):
takes_options = LDAPRetrieve.takes_options + vault_options takes_options = LDAPRetrieve.takes_options + vault_options
has_output_params = LDAPRetrieve.has_output_params
def pre_callback(self, ldap, dn, attrs_list, *keys, **options): def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
assert isinstance(dn, DN) assert isinstance(dn, DN)
@@ -1328,6 +1372,68 @@ class vault_retrieve_internal(PKQuery):
return response return response
@register()
class vault_add_owner(LDAPAddMember):
__doc__ = _('Add owners to a vault.')
takes_options = LDAPAddMember.takes_options + vault_options
member_attributes = ['owner']
member_count_out = ('%i owner added.', '%i owners added.')
has_output = (
output.Entry('result'),
output.Output(
'failed',
type=dict,
doc=_('Owners that could not be added'),
),
output.Output(
'completed',
type=int,
doc=_('Number of owners added'),
),
)
@register()
class vault_remove_owner(LDAPRemoveMember):
__doc__ = _('Remove owners from a vault.')
takes_options = LDAPRemoveMember.takes_options + vault_options
member_attributes = ['owner']
member_count_out = ('%i owner removed.', '%i owners removed.')
has_output = (
output.Entry('result'),
output.Output(
'failed',
type=dict,
doc=_('Owners that could not be removed'),
),
output.Output(
'completed',
type=int,
doc=_('Number of owners removed'),
),
)
@register()
class vault_add_member(LDAPAddMember):
__doc__ = _('Add members to a vault.')
takes_options = LDAPAddMember.takes_options + vault_options
@register()
class vault_remove_member(LDAPRemoveMember):
__doc__ = _('Remove members from a vault.')
takes_options = LDAPRemoveMember.takes_options + vault_options
@register() @register()
class kra_is_enabled(Command): class kra_is_enabled(Command):
NO_CLI = True NO_CLI = True

View File

@@ -89,7 +89,7 @@ class test_vault_plugin(Declarative):
'continue': True 'continue': True
}), }),
('vault_del', [vault_name], {'shared': True, 'continue': True}), ('vault_del', [vault_name], {'shared': True, 'continue': True}),
('vault_del', [vault_name], {'user': user_name, 'continue': True}), ('vault_del', [vault_name], {'username': user_name, 'continue': True}),
('vault_del', [standard_vault_name], {'continue': True}), ('vault_del', [standard_vault_name], {'continue': True}),
('vault_del', [symmetric_vault_name], {'continue': True}), ('vault_del', [symmetric_vault_name], {'continue': True}),
('vault_del', [asymmetric_vault_name], {'continue': True}), ('vault_del', [asymmetric_vault_name], {'continue': True}),
@@ -113,6 +113,7 @@ class test_vault_plugin(Declarative):
'objectclass': [u'top', u'ipaVault'], 'objectclass': [u'top', u'ipaVault'],
'cn': [vault_name], 'cn': [vault_name],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -154,6 +155,7 @@ class test_vault_plugin(Declarative):
% (vault_name, api.env.basedn), % (vault_name, api.env.basedn),
'cn': [vault_name], 'cn': [vault_name],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -174,6 +176,7 @@ class test_vault_plugin(Declarative):
'cn': [vault_name], 'cn': [vault_name],
'description': [u'Test vault'], 'description': [u'Test vault'],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -212,6 +215,7 @@ class test_vault_plugin(Declarative):
'objectclass': [u'top', u'ipaVault'], 'objectclass': [u'top', u'ipaVault'],
'cn': [vault_name], 'cn': [vault_name],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -257,6 +261,7 @@ class test_vault_plugin(Declarative):
% (vault_name, service_name, api.env.basedn), % (vault_name, service_name, api.env.basedn),
'cn': [vault_name], 'cn': [vault_name],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -278,6 +283,7 @@ class test_vault_plugin(Declarative):
'cn': [vault_name], 'cn': [vault_name],
'description': [u'Test vault'], 'description': [u'Test vault'],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -318,6 +324,7 @@ class test_vault_plugin(Declarative):
'objectclass': [u'top', u'ipaVault'], 'objectclass': [u'top', u'ipaVault'],
'cn': [vault_name], 'cn': [vault_name],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -363,6 +370,7 @@ class test_vault_plugin(Declarative):
% (vault_name, api.env.basedn), % (vault_name, api.env.basedn),
'cn': [vault_name], 'cn': [vault_name],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -384,6 +392,7 @@ class test_vault_plugin(Declarative):
'cn': [vault_name], 'cn': [vault_name],
'description': [u'Test vault'], 'description': [u'Test vault'],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -412,7 +421,7 @@ class test_vault_plugin(Declarative):
'vault_add', 'vault_add',
[vault_name], [vault_name],
{ {
'user': user_name, 'username': user_name,
}, },
), ),
'expected': { 'expected': {
@@ -424,6 +433,7 @@ class test_vault_plugin(Declarative):
'objectclass': [u'top', u'ipaVault'], 'objectclass': [u'top', u'ipaVault'],
'cn': [vault_name], 'cn': [vault_name],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -434,7 +444,7 @@ class test_vault_plugin(Declarative):
'vault_find', 'vault_find',
[], [],
{ {
'user': user_name, 'username': user_name,
}, },
), ),
'expected': { 'expected': {
@@ -458,7 +468,7 @@ class test_vault_plugin(Declarative):
'vault_show', 'vault_show',
[vault_name], [vault_name],
{ {
'user': user_name, 'username': user_name,
}, },
), ),
'expected': { 'expected': {
@@ -469,6 +479,7 @@ class test_vault_plugin(Declarative):
% (vault_name, user_name, api.env.basedn), % (vault_name, user_name, api.env.basedn),
'cn': [vault_name], 'cn': [vault_name],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -479,7 +490,7 @@ class test_vault_plugin(Declarative):
'vault_mod', 'vault_mod',
[vault_name], [vault_name],
{ {
'user': user_name, 'username': user_name,
'description': u'Test vault', 'description': u'Test vault',
}, },
), ),
@@ -490,6 +501,7 @@ class test_vault_plugin(Declarative):
'cn': [vault_name], 'cn': [vault_name],
'description': [u'Test vault'], 'description': [u'Test vault'],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -500,7 +512,7 @@ class test_vault_plugin(Declarative):
'vault_del', 'vault_del',
[vault_name], [vault_name],
{ {
'user': user_name, 'username': user_name,
}, },
), ),
'expected': { 'expected': {
@@ -528,6 +540,7 @@ class test_vault_plugin(Declarative):
'objectclass': [u'top', u'ipaVault'], 'objectclass': [u'top', u'ipaVault'],
'cn': [standard_vault_name], 'cn': [standard_vault_name],
'ipavaulttype': [u'standard'], 'ipavaulttype': [u'standard'],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -586,6 +599,7 @@ class test_vault_plugin(Declarative):
'cn': [symmetric_vault_name], 'cn': [symmetric_vault_name],
'ipavaulttype': [u'symmetric'], 'ipavaulttype': [u'symmetric'],
'ipavaultsalt': [fuzzy_string], 'ipavaultsalt': [fuzzy_string],
'owner_user': [u'admin'],
}, },
}, },
}, },
@@ -647,6 +661,7 @@ class test_vault_plugin(Declarative):
'cn': [asymmetric_vault_name], 'cn': [asymmetric_vault_name],
'ipavaulttype': [u'asymmetric'], 'ipavaulttype': [u'asymmetric'],
'ipavaultpublickey': [public_key], 'ipavaultpublickey': [public_key],
'owner_user': [u'admin'],
}, },
}, },
}, },