AuthMode,
CephFSStorageProvider,
JoinSourceType,
+ KeyBridgePeerPolicy,
+ KeyBridgeScopeType,
LoginAccess,
LoginCategory,
State,
_CLUSTERED = 'clustered'
_CEPHFS_PROXY = 'cephfs-proxy'
_REMOTE_CONTROL = 'remote-control'
+_KEYBRIDGE = 'keybridge'
log = logging.getLogger(__name__)
}
if share.comment is not None:
cfg['options']['comment'] = share.comment
-
if share.max_connections is not None:
cfg['options']['max connections'] = str(share.max_connections)
-
if proxy_val:
cfg['options'][f'{ceph_vfs}:proxy'] = proxy_val
+ if cephfs.fscrypt_key:
+ # enable fscrypt + keybridge
+ opts = cfg['options']
+ opts[f'{ceph_vfs}:keybridge socket'] = 'unix:/run/keybridge.s'
+ opts[f'{ceph_vfs}:keybridge scope'] = str(
+ cephfs.fscrypt_key.scope_identity().qualified()
+ )
+ opts[f'{ceph_vfs}:keybridge name'] = str(cephfs.fscrypt_key.name)
+ opts[f'{ceph_vfs}:keybridge kind'] = 'B64'
+ opts[f'{ceph_vfs}:fscrypt'] = 'keybridge'
# extend share with user+group login access lists
_generate_share_login_control(share, cfg)
# extend share with custom options
},
'shares': share_configs,
}
+ if cluster.keybridge_is_enabled:
+ _kb_default = 'default-keybridge' # typically only have one
+ cfg['configs'][cluster.cluster_id]['keybridge_config'] = _kb_default
+ cfg['keybridge'] = {_kb_default: _generate_keybridge_config(cluster)}
# insert global custom options
custom_opts = cluster.cleaned_custom_smb_global_options
if custom_opts:
features.append(_CEPHFS_PROXY)
if cluster.remote_control_is_enabled:
features.append(_REMOTE_CONTROL)
+ if cluster.keybridge_is_enabled:
+ features.append(_KEYBRIDGE)
# only one config uri can be used, the input list should be
# ordered from lowest to highest priority and the highest priority
# item that exists in the store will be used.
rc_ca_cert = _tls_uri(
cluster.remote_control.ca_cert, tls_credential_entries
)
+ kb_cert = kb_key = kb_ca_cert = None
+ if cluster.keybridge_is_enabled:
+ assert cluster.keybridge # type narrow
+ # TODO: current all KMIP scopes must share the same tls creds
+ # and that sucks. need to update keybridge to fetch cert URIs directly
+ # and stop shoveling this all through cephadm.
+ # This is especially important if we ever add non-kmip scopes that
+ # use (m)TLS.
+ kmip_scopes = [
+ s
+ for s in checked(cluster.keybridge.scopes)
+ if s.scope_identity().scope_type == KeyBridgeScopeType.KMIP
+ ]
+ if kmip_scopes:
+ kmip_scope = kmip_scopes[0]
+ kb_cert = _tls_uri(kmip_scope.kmip_cert, tls_credential_entries)
+ kb_key = _tls_uri(kmip_scope.kmip_key, tls_credential_entries)
+ kb_ca_cert = _tls_uri(
+ kmip_scope.kmip_ca_cert, tls_credential_entries
+ )
return SMBSpec(
service_id=cluster.cluster_id,
placement=cluster.placement,
remote_control_ssl_cert=rc_cert,
remote_control_ssl_key=rc_key,
remote_control_ca_cert=rc_ca_cert,
+ keybridge_kmip_ssl_cert=kb_cert,
+ keybridge_kmip_ssl_key=kb_key,
+ keybridge_kmip_ca_cert=kb_ca_cert,
)
+def _generate_keybridge_config(cluster: resources.Cluster) -> Dict[str, Any]:
+ """generate the keybridge subsection for the sambacc config."""
+ # NOTE: the tls credentials are handled by cephadm and are passed
+ # to the keybridge server command line (by path). That's why they are
+ # not mentioned here. This could change in the future.
+ scopes: List[Simplified] = []
+ for scope in checked(cluster.keybridge).scopes or []:
+ kbsi = scope.scope_identity()
+ scope_config: Simplified = {'name': str(kbsi.qualified())}
+ if kbsi.scope_type is KeyBridgeScopeType.KMIP:
+ scope_config['hostnames'] = checked(scope.kmip_hosts)
+ if scope.kmip_port:
+ scope_config['port'] = checked(scope.kmip_port)
+ scopes.append(scope_config)
+ cfg: Simplified = {'scopes': scopes}
+ if (
+ checked(cluster.keybridge).use_peer_policy
+ is KeyBridgePeerPolicy.RESTRICTED
+ ):
+ cfg['verify_peer'] = {
+ "check_pid": "1+",
+ "check_uid": "0",
+ "check_gid": "0",
+ }
+ return cfg
+
+
def _swap_pending_cluster_info(
store: ConfigStore,
change_group: ClusterChangeGroup,