diff --git a/ui/docs/msd-api.md b/ui/docs/msd-api.md index 6d87ce0b23b..451be49597e 100644 --- a/ui/docs/msd-api.md +++ b/ui/docs/msd-api.md @@ -16,11 +16,11 @@ obj = { ### postTransportPolicyValidationRequest(*obj, function(err, json, response) { }); `POST /transportpolicy/validate` -API to validate microsegmentation policies against network policies +API to validate micro-segmentation policies against network policies ``` obj = { - "transportPolicy": "" // Struct representing microsegmentation policy entered by the user + "transportPolicy": "" // Struct representing micro-segmentation policy entered by the user }; ``` *Types:* [`TransportPolicyValidationRequest `](#transportpolicyvalidationrequest-struct) @@ -50,6 +50,52 @@ obj = { ``` *Types:* [`DomainName `](#domainname-string) +### putTransportPolicyRequest(*obj, function(err, json, response) { }); + +`PUT /domain/{domainName}/service/{serviceName}/transportpolicy` +This API endpoint facilitates the creation or update of a transport policy for a specified domain and service. It is designed exclusively for the purpose of creating or updating transport policies, and does not support mixed-case scenarios. Once a transport policy is established, the destination service, protocol, and both source and destination ports become non-editable. To modify any of these fields, it is necessary to create a new policy and delete the old one. + +``` +obj = { + "domainName": "", // name of the domain + "serviceName": "", // Name of the service + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request + "payload": "" // Struct representing input transport policy +}; +``` +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`TransportPolicyRequest `](#transportpolicyrequest-struct) + +### getTransportPolicyRules(*obj, function(err, json, response) { }); + +`GET /domain/{domainName}/service/{serviceName}/transportpolicies` +API endpoint to get the transport policy rules defined in Athenz for a given domain and service + +``` +obj = { + "domainName": "", // name of the domain + "serviceName": "", // Name of the service + "matchingTag": "" // (optional) Retrieved from the previous request, this timestamp specifies to the server to return any policies modified since this time +}; +``` +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string) + +### deleteTransportPolicyRules(*obj, function(err, json, response) { }); + +`DELETE /domain/{domainName}/service/{serviceName}/transportpolicy/{id}` +API endpoint to delete the transport policy Upon successful completion of this delete request, the server will return NO_CONTENT status code without any data (no object will be returned). + +``` +obj = { + "domainName": "", // Name of the domain + "serviceName": "", // Name of the service + "id": "", // Id of the assertion representing the transport policy + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request +}; +``` +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string) + ### getWorkloads(*obj, function(err, json, response) { }); `GET /domain/{domainName}/service/{serviceName}/workloads` @@ -85,7 +131,8 @@ Api to perform a dynamic workload PUT operation for a domain and service Workloa obj = { "domainName": "", // name of the domain "serviceName": "", // name of the service - "options": "" // metadata about the dynamic workload + "options": "", // metadata about the dynamic workload + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`WorkloadOptions `](#workloadoptions-struct) @@ -99,7 +146,8 @@ Api to perform a dynamic workload DELETE operation for a domain, service, and in obj = { "domainName": "", // name of the domain "serviceName": "", // name of the service - "instanceId": "" // unique instance id within provider's namespace + "instanceId": "", // unique instance id within provider's namespace + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`PathElement `](#pathelement-string) @@ -113,7 +161,8 @@ Api to perform a static workload PUT operation for a domain and service obj = { "domainName": "", // name of the domain "serviceName": "", // name of the service - "staticWorkload": "" // Struct representing static workload entered by the user + "staticWorkload": "", // Struct representing static workload entered by the user + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`StaticWorkload `](#staticworkload-struct) @@ -127,10 +176,11 @@ Api to perform a static workload DELETE operation for a domain, service, and ins obj = { "domainName": "", // name of the domain "serviceName": "", // name of the service - "name": "" // name associated with the workload. In most cases will be a FQDN + "name": "", // name associated with the workload. In most cases will be a FQDN + "resourceOwner": "" // (optional) Resource owner for the request }; ``` -*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string) +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`StaticWorkloadName `](#staticworkloadname-string) ### getStaticWorkloadServices(*obj, function(err, json, response) { }); @@ -158,6 +208,49 @@ obj = { ``` *Types:* [`DomainName `](#domainname-string) +### postBulkWorkloadRequest(*obj, function(err, json, response) { }); + +`POST /workloads` +Read only endpoint to fetch workloads for a list of services grouped by domains + +``` +obj = { + "request": "", // workload search request + "matchingTag": "" // (optional) Retrieved from the previous request, this timestamp specifies to the server to return any workloads modified since this time +}; +``` +*Types:* [`BulkWorkloadRequest `](#bulkworkloadrequest-struct) + +### putCompositeInstance(*obj, function(err, json, response) { }); + +`PUT /domain/{domainName}/service/{serviceName}/workload/discover/instance` +Api to discover an additional instance which can have static or dynamic or both IPs + +``` +obj = { + "domainName": "", // name of the domain + "serviceName": "", // name of the service + "instance": "", // Generic instance + "resourceOwner": "" // (optional) Resource owner for the request +}; +``` +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`CompositeInstance `](#compositeinstance-struct) + +### deleteWorkloads(*obj, function(err, json, response) { }); + +`DELETE /domain/{domainName}/service/{serviceName}/workload/discover/instance/{instance}` +Api to delete an additional instance which can have static or dynamic or both IPs + +``` +obj = { + "domainName": "", // name of the domain + "serviceName": "", // name of the service + "instance": "", // instance name/id/key + "resourceOwner": "" // (optional) Resource owner for the request +}; +``` +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`SimpleName `](#simplename-string) + ### postNetworkPolicyChangeImpactRequest(*obj, function(err, json, response) { }); `POST /transportpolicy/evaluatenetworkpolicychange` @@ -170,6 +263,21 @@ obj = { ``` *Types:* [`NetworkPolicyChangeImpactRequest `](#networkpolicychangeimpactrequest-struct) +### postKubernetesNetworkPolicyRequest(*obj, function(err, json, response) { }); + +`POST /domain/{domainName}/service/{serviceName}/kubernetesnetworkpolicy` +API endpoint to get the Kubernetes network policy converted from the corresponding MSD policy + +``` +obj = { + "domainName": "", // Name of the domain + "serviceName": "", // Name of the service + "request": "", // Struct representing input options based on the cluster context + "matchingTag": "" // (optional) Retrieved from the previous request, this timestamp specifies to the server to return any policies modified since this time +}; +``` +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`KubernetesNetworkPolicyRequest `](#kubernetesnetworkpolicyrequest-struct) + ### getRdl.Schema(*obj, function(err, json, response) { }); `GET /schema` @@ -375,6 +483,46 @@ ServiceName in TransportPolicySubject should allow * to indicate ANY } ``` +### StaticWorkloadComponent `` + +``` +{ + "type": "String", + "name": "StaticWorkloadComponent", + "pattern": "[a-zA-Z0-9][a-zA-Z0-9-:._]*" +} +``` + +### StaticWorkloadFQDN `` + +``` +{ + "type": "String", + "name": "StaticWorkloadFQDN", + "pattern": "([a-zA-Z0-9][a-zA-Z0-9-:._]*\\.)*[a-zA-Z0-9][a-zA-Z0-9-:._]*" +} +``` + +### StaticWorkloadName `` + +``` +{ + "type": "String", + "name": "StaticWorkloadName", + "pattern": "(([a-zA-Z0-9][a-zA-Z0-9-:._]*\\.)*[a-zA-Z0-9][a-zA-Z0-9-:._]*)(\\/[0-9]{1,3})?" +} +``` + +### TransportPolicySubjectExternal `` + +``` +{ + "type": "String", + "name": "TransportPolicySubjectExternal", + "pattern": "(([a-zA-Z0-9][a-zA-Z0-9-:._]*\\.)*[a-zA-Z0-9][a-zA-Z0-9-:._]*)(\\/[0-9]{1,3})?" +} +``` + ### TransportPolicyEnforcementState `` Types of transport policy enforcement states @@ -511,6 +659,46 @@ Subject for a transport policy "type": "TransportPolicySubjectServiceName", "optional": false, "comment": "Name of the service" + }, + { + "name": "externalPeer", + "type": "TransportPolicySubjectExternal", + "optional": true, + "comment": "External peer ( not in Athenz )" + } + ], + "closed": false +} +``` + +### TransportPolicySubjectSelectorRequirement `` + +A subject selector requirement is a selector that contains value, a key, and an operator that relates the key and value. + + +``` +{ + "type": "Struct", + "name": "TransportPolicySubjectSelectorRequirement", + "comment": "A subject selector requirement is a selector that contains value, a key, and an operator that relates the key and value.", + "fields": [ + { + "name": "key", + "type": "String", + "optional": false, + "comment": "key that the selector applies to" + }, + { + "name": "operator", + "type": "String", + "optional": false, + "comment": "Operator that is applied to the key and value" + }, + { + "name": "value", + "type": "String", + "optional": false, + "comment": "Value that the selector applies to" } ], "closed": false @@ -547,6 +735,13 @@ Transport policy condition. Used to specify additional restrictions for the subj "optional": true, "comment": "Scope of transport policy", "items": "TransportPolicyScope" + }, + { + "name": "additionalConditions", + "type": "Array", + "optional": true, + "comment": "List of any additional conditions", + "items": "TransportPolicySubjectSelectorRequirement" } ], "closed": false @@ -708,6 +903,12 @@ Transport policy ingress rule "optional": false, "comment": "Assertion id associated with this transport policy" }, + { + "name": "identifier", + "type": "EntityName", + "optional": true, + "comment": "Policy Identifier" + }, { "name": "lastModified", "type": "Timestamp", @@ -748,6 +949,12 @@ Transport policy egress rule "optional": false, "comment": "Assertion id associated with this transport policy" }, + { + "name": "identifier", + "type": "EntityName", + "optional": true, + "comment": "Policy Identifier" + }, { "name": "lastModified", "type": "Timestamp", @@ -902,6 +1109,68 @@ List of TransportPolicyValidationResponse } ``` +### TransportPolicyRequest `` + +Input to create a transport policy + + +``` +{ + "type": "Struct", + "name": "TransportPolicyRequest", + "comment": "Input to create a transport policy", + "fields": [ + { + "name": "direction", + "type": "TransportPolicyTrafficDirection", + "optional": false, + "comment": "Direction of network traffic" + }, + { + "name": "identifier", + "type": "EntityName", + "optional": false, + "comment": "Policy Identifier" + }, + { + "name": "subject", + "type": "TransportPolicySubject", + "optional": false, + "comment": "Subject for the policy" + }, + { + "name": "conditions", + "type": "Array", + "optional": true, + "comment": "List of transport policy conditions", + "items": "TransportPolicyCondition" + }, + { + "name": "sourcePorts", + "type": "Array", + "optional": false, + "comment": "List of source network traffic ports", + "items": "TransportPolicyPort" + }, + { + "name": "destinationPorts", + "type": "Array", + "optional": false, + "comment": "List of destination network traffic ports", + "items": "TransportPolicyPort" + }, + { + "name": "peers", + "type": "Array", + "optional": true, + "comment": "Source or destination of the policy depending on direction", + "items": "TransportPolicySubject" + } + ], + "closed": false +} +``` + ### StaticWorkloadType `` Enum representing defined types of static workloads. @@ -1065,7 +1334,7 @@ workload type describing workload indirectly associated with an identity ( witho }, { "name": "name", - "type": "String", + "type": "StaticWorkloadName", "optional": true, "comment": "name associated with the workload. In most cases will be a FQDN" }, @@ -1191,115 +1460,282 @@ list of services } ``` -### NetworkPolicyChangeEffect `` - -IMPACT indicates that a change in network policy will interfere with workings of one or more transport policies NO_IMAPCT indicates that a change in network policy will not interfere with workings of any transport policy - - -``` -{ - "type": "Enum", - "name": "NetworkPolicyChangeEffect", - "comment": "IMPACT indicates that a change in network policy will interfere with workings of one or more transport policies NO_IMAPCT indicates that a change in network policy will not interfere with workings of any transport policy", - "elements": [ - { - "symbol": "IMPACT" - }, - { - "symbol": "NO_IMPACT" - } - ] -} -``` - -### IPBlock `` +### DomainServices `` -Struct representing ip blocks used by network policy in CIDR (Classless inter-domain routing) format +request type to search all workloads for a domain and selected list of its services ``` { "type": "Struct", - "name": "IPBlock", - "comment": "Struct representing ip blocks used by network policy in CIDR (Classless inter-domain routing) format", + "name": "DomainServices", + "comment": "request type to search all workloads for a domain and selected list of its services", "fields": [ { - "name": "cidr", - "type": "String", + "name": "domainName", + "type": "DomainName", "optional": false, - "comment": "cidr notation. can be used for ipv4 or ipv6" + "comment": "name of the domain" + }, + { + "name": "serviceNames", + "type": "Array", + "optional": false, + "comment": "list of service names", + "items": "EntityName" } ], "closed": false } ``` -### NetworkPolicyPort `` +### BulkWorkloadRequest `` -network policy port. +request type to search all workloads for a list of services grouped by domains ``` { - "type": "PolicyPort", - "name": "NetworkPolicyPort", - "comment": "network policy port.", + "type": "Struct", + "name": "BulkWorkloadRequest", + "comment": "request type to search all workloads for a list of services grouped by domains", "fields": [ { - "name": "protocol", - "type": "TransportPolicyProtocol", + "name": "domainServices", + "type": "Array", "optional": false, - "comment": "protocol used by the network policy" + "comment": "list of services, grouped by domain", + "items": "DomainServices" + }, + { + "name": "fetchStaticTypeWorkloads", + "type": "Bool", + "optional": true, + "comment": "whether to fetch static type workloads", + "default": true + }, + { + "name": "fetchDynamicTypeWorkloads", + "type": "Bool", + "optional": true, + "comment": "whether to fetch dynamic type workloads", + "default": true + }, + { + "name": "applicableStaticTypes", + "type": "Array", + "optional": true, + "comment": "list of applicable static workload types, if not set then that means all. Applicable only if fetchStaticTypeWorkloads is enabled", + "items": "StaticWorkloadType" + }, + { + "name": "resolveStaticWorkloads", + "type": "Bool", + "optional": true, + "comment": "resolve static workloads to IPs, if applicable", + "default": false } ], "closed": false } ``` -### NetworkPolicyPorts `` +### BulkWorkloadResponse `` -allows creating a unique tuple of source and destination ports +response of a bulk workload search request ``` { "type": "Struct", - "name": "NetworkPolicyPorts", - "comment": "allows creating a unique tuple of source and destination ports", + "name": "BulkWorkloadResponse", + "comment": "response of a bulk workload search request", "fields": [ { - "name": "sourcePorts", + "name": "unmodifiedServices", "type": "Array", "optional": false, - "comment": "list of source ports", - "items": "NetworkPolicyPort" + "comment": "list of services grouped by domain, those are not changed since time stamp in matchingTag", + "items": "DomainServices" }, { - "name": "destinationPorts", - "type": "Array", + "name": "workloads", + "type": "Workloads", "optional": false, - "comment": "list of destination ports", - "items": "NetworkPolicyPort" + "comment": "matching workloads" } ], "closed": false } ``` -### NetworkPolicyChangeImpactRequest `` +### CompositeInstance `` -struct representing input details for evaluating network policies change impact on transport policies +generic instance ``` { "type": "Struct", - "name": "NetworkPolicyChangeImpactRequest", - "comment": "struct representing input details for evaluating network policies change impact on transport policies", + "name": "CompositeInstance", + "comment": "generic instance", "fields": [ { - "name": "from", - "type": "Array", + "name": "domainName", + "type": "DomainName", + "optional": false, + "comment": "name of the domain" + }, + { + "name": "serviceName", + "type": "EntityName", + "optional": false, + "comment": "name of the service" + }, + { + "name": "instance", + "type": "SimpleName", + "optional": false, + "comment": "instance name/id" + }, + { + "name": "instanceType", + "type": "String", + "optional": true, + "comment": "instance type" + }, + { + "name": "provider", + "type": "String", + "optional": true, + "comment": "name of the instance provider, for example aws/gcp" + }, + { + "name": "certExpiryTime", + "type": "Timestamp", + "optional": true, + "comment": "certificate expiry time (ex: getNotAfter), if applicable" + }, + { + "name": "certIssueTime", + "type": "Timestamp", + "optional": true, + "comment": "certificate issue time (ex: getNotBefore), if applicable" + } + ], + "closed": false +} +``` + +### NetworkPolicyChangeEffect `` + +IMPACT indicates that a change in network policy will interfere with workings of one or more transport policies NO_IMPACT indicates that a change in network policy will not interfere with workings of any transport policy + + +``` +{ + "type": "Enum", + "name": "NetworkPolicyChangeEffect", + "comment": "IMPACT indicates that a change in network policy will interfere with workings of one or more transport policies NO_IMPACT indicates that a change in network policy will not interfere with workings of any transport policy", + "elements": [ + { + "symbol": "IMPACT" + }, + { + "symbol": "NO_IMPACT" + } + ] +} +``` + +### IPBlock `` + +Struct representing ip blocks used by network policy in CIDR (Classless inter-domain routing) format + + +``` +{ + "type": "Struct", + "name": "IPBlock", + "comment": "Struct representing ip blocks used by network policy in CIDR (Classless inter-domain routing) format", + "fields": [ + { + "name": "cidr", + "type": "String", + "optional": false, + "comment": "cidr notation. can be used for ipv4 or ipv6" + } + ], + "closed": false +} +``` + +### NetworkPolicyPort `` + +network policy port. + + +``` +{ + "type": "PolicyPort", + "name": "NetworkPolicyPort", + "comment": "network policy port.", + "fields": [ + { + "name": "protocol", + "type": "TransportPolicyProtocol", + "optional": false, + "comment": "protocol used by the network policy" + } + ], + "closed": false +} +``` + +### NetworkPolicyPorts `` + +allows creating a unique tuple of source and destination ports + + +``` +{ + "type": "Struct", + "name": "NetworkPolicyPorts", + "comment": "allows creating a unique tuple of source and destination ports", + "fields": [ + { + "name": "sourcePorts", + "type": "Array", + "optional": false, + "comment": "list of source ports", + "items": "NetworkPolicyPort" + }, + { + "name": "destinationPorts", + "type": "Array", + "optional": false, + "comment": "list of destination ports", + "items": "NetworkPolicyPort" + } + ], + "closed": false +} +``` + +### NetworkPolicyChangeImpactRequest `` + +struct representing input details for evaluating network policies change impact on transport policies + + +``` +{ + "type": "Struct", + "name": "NetworkPolicyChangeImpactRequest", + "comment": "struct representing input details for evaluating network policies change impact on transport policies", + "fields": [ + { + "name": "from", + "type": "Array", "optional": false, "comment": "from ip address range list in cidr format", "items": "IPBlock" @@ -1382,6 +1818,362 @@ struct representing response of evaluating network policies change impact on tra } ``` +### KubernetesLabelSelectorRequirement `` + +A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + + +``` +{ + "type": "Struct", + "name": "KubernetesLabelSelectorRequirement", + "comment": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.", + "fields": [ + { + "name": "key", + "type": "String", + "optional": false, + "comment": "Label key that the selector applies to" + }, + { + "name": "operator", + "type": "String", + "optional": false, + "comment": "Operator that is applied to the key. Valid operators are In, NotIn, Exists and DoesNotExist." + }, + { + "name": "values", + "type": "Array", + "optional": true, + "comment": "Array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.", + "items": "String" + } + ], + "closed": false +} +``` + +### KubernetesLabelSelector `` + +A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects. + + +``` +{ + "type": "Struct", + "name": "KubernetesLabelSelector", + "comment": "A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects.", + "fields": [ + { + "name": "matchExpressions", + "type": "Array", + "optional": false, + "comment": "Array of label selector requirements. The requirements are ANDed.", + "items": "KubernetesLabelSelectorRequirement" + }, + { + "name": "matchLabels", + "type": "Map", + "optional": false, + "comment": "Map of label key/value pairs", + "items": "String", + "keys": "String" + } + ], + "closed": false +} +``` + +### KubernetesNetworkPolicyPort `` + +Kubernetes network policy port range + + +``` +{ + "type": "PolicyPort", + "name": "KubernetesNetworkPolicyPort", + "comment": "Kubernetes network policy port range", + "fields": [ + { + "name": "protocol", + "type": "TransportPolicyProtocol", + "optional": false, + "comment": "Network policy protocol. Allowed values: TCP, UDP." + } + ], + "closed": false +} +``` + +### KubernetesIPBlock `` + +Kubernetes network policy IP block source/target + + +``` +{ + "type": "Struct", + "name": "KubernetesIPBlock", + "comment": "Kubernetes network policy IP block source/target", + "fields": [ + { + "name": "cidr", + "type": "String", + "optional": false, + "comment": "CIDR block representing IP range for source/target" + }, + { + "name": "except", + "type": "Array", + "optional": true, + "comment": "Exception for CIDR blocks, if needed", + "items": "String" + } + ], + "closed": false +} +``` + +### KubernetesNetworkPolicyPeer `` + +Kubernetes network policy peer (source/target) + + +``` +{ + "type": "Struct", + "name": "KubernetesNetworkPolicyPeer", + "comment": "Kubernetes network policy peer (source/target)", + "fields": [ + { + "name": "podSelector", + "type": "KubernetesLabelSelector", + "optional": true, + "comment": "Kubernetes pod selector for the network policy source/target" + }, + { + "name": "namespaceSelector", + "type": "KubernetesLabelSelector", + "optional": true, + "comment": "Kubernetes namespace selector for the network policy source/target" + }, + { + "name": "ipBlock", + "type": "KubernetesIPBlock", + "optional": true, + "comment": "IP block for the network policy source/target" + } + ], + "closed": false +} +``` + +### KubernetesNetworkPolicyIngressRule `` + +Kubernetes network policy ingress rule + + +``` +{ + "type": "Struct", + "name": "KubernetesNetworkPolicyIngressRule", + "comment": "Kubernetes network policy ingress rule", + "fields": [ + { + "name": "from", + "type": "Array", + "optional": true, + "comment": "Network policy source, when empty all sources are allowed", + "items": "KubernetesNetworkPolicyPeer" + }, + { + "name": "ports", + "type": "Array", + "optional": true, + "comment": "Ingress port(s), when empty all ports are allowed", + "items": "KubernetesNetworkPolicyPort" + } + ], + "closed": false +} +``` + +### KubernetesNetworkPolicyEgressRule `` + +Kubernetes network policy egress rule + + +``` +{ + "type": "Struct", + "name": "KubernetesNetworkPolicyEgressRule", + "comment": "Kubernetes network policy egress rule", + "fields": [ + { + "name": "to", + "type": "Array", + "optional": true, + "comment": "Network policy target, when empty all sources are allowed", + "items": "KubernetesNetworkPolicyPeer" + }, + { + "name": "ports", + "type": "Array", + "optional": true, + "comment": "Egress port(s), when empty all ports are allowed", + "items": "KubernetesNetworkPolicyPort" + } + ], + "closed": false +} +``` + +### KubernetesNetworkPolicySpec `` + +Kubernetes network policy spec + + +``` +{ + "type": "Struct", + "name": "KubernetesNetworkPolicySpec", + "comment": "Kubernetes network policy spec", + "fields": [ + { + "name": "podSelector", + "type": "KubernetesLabelSelector", + "optional": false, + "comment": "Kubernetes pod selector for the network policy target" + }, + { + "name": "policyTypes", + "type": "Array", + "optional": false, + "comment": "Network policy types - Ingress, Egress", + "items": "String" + }, + { + "name": "ingress", + "type": "Array", + "optional": true, + "comment": "Ingress network policy rules, if empty then all ingress traffic is blocked", + "items": "KubernetesNetworkPolicyIngressRule" + }, + { + "name": "egress", + "type": "Array", + "optional": true, + "comment": "Egress network policy rules, if empty then all egress traffic is blocked", + "items": "KubernetesNetworkPolicyEgressRule" + } + ], + "closed": false +} +``` + +### KubernetesNetworkPolicyRequest `` + +Request object containing Kubernetes network policy inputs + + +``` +{ + "type": "Struct", + "name": "KubernetesNetworkPolicyRequest", + "comment": "Request object containing Kubernetes network policy inputs", + "fields": [ + { + "name": "athenzDomainLabel", + "type": "String", + "optional": true, + "comment": "Label key name used on pods to identify Athenz domain" + }, + { + "name": "athenzServiceLabel", + "type": "String", + "optional": false, + "comment": "Label key name used on pods to identify Athenz service" + }, + { + "name": "networkPolicyType", + "type": "String", + "optional": true, + "comment": "Network policy type, default is vanilla Kubernetes" + }, + { + "name": "requestedApiVersion", + "type": "String", + "optional": true, + "comment": "Requested network policy apiVersion" + }, + { + "name": "networkPolicyNamespace", + "type": "String", + "optional": true, + "comment": "Kubernetes namespace for the network policy object" + }, + { + "name": "domainLabelAsNamespaceSelector", + "type": "Bool", + "optional": true, + "comment": "Use athenzDomainLabel as namespace selector", + "default": false + }, + { + "name": "domainInServiceLabel", + "type": "Bool", + "optional": true, + "comment": "Use Athenz domain name in service label", + "default": false + } + ], + "closed": false +} +``` + +### KubernetesNetworkPolicyResponse `` + +Response object containing Kubernetes network policy + + +``` +{ + "type": "Struct", + "name": "KubernetesNetworkPolicyResponse", + "comment": "Response object containing Kubernetes network policy", + "fields": [ + { + "name": "apiVersion", + "type": "String", + "optional": false, + "comment": "Kubernetes network policy apiVersion" + }, + { + "name": "kind", + "type": "String", + "optional": false, + "comment": "Kubernetes network policy kind" + }, + { + "name": "metadata", + "type": "Map", + "optional": false, + "comment": "Kubernetes network policy metadata", + "items": "String", + "keys": "String" + }, + { + "name": "spec", + "type": "KubernetesNetworkPolicySpec", + "optional": false, + "comment": "Kubernetes network policy spec" + } + ], + "closed": false +} +``` + ### rdl.Identifier `` All names need to be of this restricted string type @@ -2362,4 +3154,4 @@ A Schema is a container for types and resources. It is self-contained (no extern ``` -*generated on Wed Sep 27 2023 11:23:44 GMT-0700 (Pacific Daylight Time)* \ No newline at end of file +*generated on Tue Nov 26 2024 15:18:35 GMT+0000 (Greenwich Mean Time)* \ No newline at end of file diff --git a/ui/docs/zms-api.md b/ui/docs/zms-api.md index 976bff5e703..2510e729d53 100644 --- a/ui/docs/zms-api.md +++ b/ui/docs/zms-api.md @@ -31,14 +31,14 @@ obj = { "roleName": "", // (optional) restrict the domain names where the specified user is in this role - see roleMember "subscription": "", // (optional) restrict to domain names that have specified azure subscription name "project": "", // (optional) restrict to domain names that have specified gcp project name - "tagKey": "", // (optional) flag to query all domains that have a given tagName - "tagValue": "", // (optional) flag to query all domains that have a given tag name and value + "tagKey": "", // (optional) flag to query all domains that have a given tagName + "tagValue": "", // (optional) flag to query all domains that have a given tag name and value "businessService": "", // (optional) restrict to domain names that have specified business service name "productId": "", // (optional) restrict the domain names that have specified product id "modifiedSince": "" // (optional) This header specifies to the server to return any domains modified since this HTTP date }; ``` -*Types:* [`ResourceName `](#resourcename-string), [`CompoundName `](#compoundname-string) +*Types:* [`ResourceName `](#resourcename-string), [`TagKey `](#tagkey-string), [`TagCompoundValue `](#tagcompoundvalue-string) ### postTopLevelDomain(*obj, function(err, json, response) { }); @@ -48,6 +48,7 @@ Create a new top level domain. This is a privileged action for the "sys.auth" ad ``` obj = { "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "detail": "" // TopLevelDomain object to be created }; ``` @@ -62,6 +63,7 @@ Create a new subdomain. The domain administrators of the {parent} domain have th obj = { "parent": "", // name of the parent domain "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "detail": "" // Subdomain object to be created }; ``` @@ -76,6 +78,7 @@ Create a new user domain. The user domain will be created in the user top level obj = { "name": "", // name of the domain which will be the user id "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "detail": "" // UserDomain object to be created }; ``` @@ -89,7 +92,8 @@ Delete the specified domain. This is a privileged action for the "sys.auth" adm ``` obj = { "name": "", // name of the domain to be deleted - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`SimpleName `](#simplename-string) @@ -97,13 +101,14 @@ obj = { ### deleteSubDomain(*obj, function(err, json, response) { }); `DELETE /subdomain/{parent}/{name}` -Delete the specified subdomain. Caller must have domain delete permissions in parent. Upon successful completion of this delete request, the server will return NO_CONTENT status code without any data (no object will be returned). +Delete the specified subdomain. Caller must have domain delete permissions in parent or in the domain itself. Therefore, the RDL requires authentication only and the server will perform the authorization check based on the caller's identity. Upon successful completion of this delete request, the server will return NO_CONTENT status code without any data (no object will be returned). ``` obj = { "parent": "", // name of the parent domain "name": "", // name of the subdomain to be deleted - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`SimpleName `](#simplename-string) @@ -116,7 +121,8 @@ Delete the specified userdomain. Caller must have domain delete permissions in t ``` obj = { "name": "", // name of the domain to be deleted which will be the user id - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`SimpleName `](#simplename-string) @@ -130,6 +136,7 @@ Update the specified top level domain metadata. Note that entities in the domain obj = { "name": "", // name of the domain to be updated "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "detail": "" // DomainMeta object with updated attribute values }; ``` @@ -242,6 +249,20 @@ obj = { }; ``` +### putResourceDomainOwnership(*obj, function(err, json, response) { }); + +`PUT /domain/{domainName}/ownership` +Set the resource ownership for the given domain + +``` +obj = { + "domainName": "", // name of the domain + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwnership": "" // resource ownership to be set for the given domain +}; +``` +*Types:* [`DomainName `](#domainname-string), [`ResourceDomainOwnership `](#resourcedomainownership-struct) + ### getDomainDataCheck(*obj, function(err, json, response) { }); `GET /domain/{domainName}/check` @@ -331,11 +352,11 @@ Get the list of all roles in a domain with optional flag whether or not include obj = { "domainName": "", // name of the domain "members": "", // return list of members in the role - "tagKey": "", // (optional) flag to query all roles that have a given tagName - "tagValue": "" // (optional) flag to query all roles that have a given tag name and value + "tagKey": "", // (optional) flag to query all roles that have a given tagName + "tagValue": "" // (optional) flag to query all roles that have a given tag name and value }; ``` -*Types:* [`DomainName `](#domainname-string), [`CompoundName `](#compoundname-string) +*Types:* [`DomainName `](#domainname-string), [`TagKey `](#tagkey-string), [`TagCompoundValue `](#tagcompoundvalue-string) ### getRole(*obj, function(err, json, response) { }); @@ -364,6 +385,7 @@ obj = { "roleName": "", // name of the role to be added/updated "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. "returnObj": "", // (optional) Return object param updated object back. + "resourceOwner": "", // (optional) Resource owner for the request "role": "" // Role object to be added/updated in the domain }; ``` @@ -378,7 +400,8 @@ Delete the specified role. Upon successful completion of this delete request, th obj = { "domainName": "", // name of the domain "roleName": "", // name of the role to be deleted - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string) @@ -425,7 +448,7 @@ obj = { ### getDomainRoleMember(*obj, function(err, json, response) { }); `GET /role` -Fetch all the roles across domains by either calling or specified principal The optional expand argument will include all direct and indirect roles, however, it will force authorization that you must be either the principal or for service accounts have update access to the service identity: 1. authenticated principal is the same as the check principal 2. system authorized ("access", "sys.auth:meta.role.lookup") 3. service admin ("update", "{principal}") +Fetch all the roles across domains by either calling or specified principal The optional expand argument will include all direct and indirect roles, however, it will force authorization that you must be either the principal or for service accounts have update access to the service identity: 1. authenticated principal is the same as the check principal 2. system authorized ("access", "sys.auth:meta.role.lookup") 3. service admin ("update", "{principal}") 4. domain authorized ("access", "{domainName}:meta.role.lookup") if domainName is provided ``` obj = { @@ -439,7 +462,7 @@ obj = { ### putMembership(*obj, function(err, json, response) { }); `PUT /domain/{domainName}/role/{roleName}/member/{memberName}` -Add the specified user to the role's member list. If the role is neither auditEnabled nor selfserve, then it will use authorize ("update", "{domainName}:role.{roleName}") or ("update_members", "{domainName}:role.{roleName}"). This only allows access to members and not role attributes. otherwise membership will be sent for approval to either designated delegates ( in case of auditEnabled roles ) or to domain admins ( in case of selfserve roles ) +Add the specified user to the role's member list. If the role is selfRenewEnabled, then an existing member may extend their expiration time by the configured number of minutes (selfRenewMins) by calling this API regardless or not the user is expired or active. If the role is neither auditEnabled nor selfserve, then it will use authorize ("update", "{domainName}:role.{roleName}") or ("update_members", "{domainName}:role.{roleName}"). This only allows access to members and not role attributes. otherwise membership will be sent for approval to either designated delegates ( in case of auditEnabled roles ) or to domain admins ( in case of selfserve roles ) ``` obj = { @@ -448,6 +471,7 @@ obj = { "memberName": "", // name of the user to be added as a member "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. "returnObj": "", // (optional) Return object param updated object back. + "resourceOwner": "", // (optional) Resource owner for the request "membership": "" // Membership object (must contain role/member names as specified in the URI) }; ``` @@ -463,7 +487,8 @@ obj = { "domainName": "", // name of the domain "roleName": "", // name of the role "memberName": "", // name of the user to be removed as a member - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`MemberName `](#membername-string) @@ -523,6 +548,7 @@ obj = { "domainName": "", // name of the domain to be updated "roleName": "", // name of the role "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "detail": "" // RoleMeta object with updated attribute values }; ``` @@ -547,7 +573,7 @@ obj = { ### putRole(*obj, function(err, json, response) { }); `PUT /domain/{domainName}/role/{roleName}/review` -Review role membership and take action to either extend and/or delete existing members. +Review role membership and take action to either extend and/or delete existing members. The required authorization includes two options: 1. ("update", "{domainName}:role.{roleName}") 2. ("update_members", "{domainName}:role.{roleName}") ``` obj = { @@ -555,11 +581,27 @@ obj = { "roleName": "", // name of the role "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. "returnObj": "", // (optional) Return object param updated object back. + "resourceOwner": "", // (optional) Resource owner for the request "role": "" // Role object with updated and/or deleted members }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`Role `](#role-rolemeta) +### putResourceRoleOwnership(*obj, function(err, json, response) { }); + +`PUT /domain/{domainName}/role/{roleName}/ownership` +Set the resource ownership for the given role + +``` +obj = { + "domainName": "", // name of the domain + "roleName": "", // name of the role + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwnership": "" // resource ownership to be set for the given role +}; +``` +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`ResourceRoleOwnership `](#resourceroleownership-struct) + ### getGroups(*obj, function(err, json, response) { }); `GET /domain/{domainName}/groups` @@ -569,11 +611,11 @@ Get the list of all groups in a domain with optional flag whether or not include obj = { "domainName": "", // name of the domain "members": "", // return list of members in the group - "tagKey": "", // (optional) flag to query all groups that have a given tagName - "tagValue": "" // (optional) flag to query all groups that have a given tag name and value + "tagKey": "", // (optional) flag to query all groups that have a given tagName + "tagValue": "" // (optional) flag to query all groups that have a given tag name and value }; ``` -*Types:* [`DomainName `](#domainname-string), [`CompoundName `](#compoundname-string) +*Types:* [`DomainName `](#domainname-string), [`TagKey `](#tagkey-string), [`TagCompoundValue `](#tagcompoundvalue-string) ### getGroup(*obj, function(err, json, response) { }); @@ -601,6 +643,7 @@ obj = { "groupName": "", // name of the group to be added/updated "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. "returnObj": "", // (optional) Return object param updated object back. + "resourceOwner": "", // (optional) Resource owner for the request "group": "" // Group object to be added/updated in the domain }; ``` @@ -615,7 +658,8 @@ Delete the specified group. Upon successful completion of this delete request, t obj = { "domainName": "", // name of the domain "groupName": "", // name of the group to be deleted - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string) @@ -651,7 +695,7 @@ obj = { ### putGroupMembership(*obj, function(err, json, response) { }); `PUT /domain/{domainName}/group/{groupName}/member/{memberName}` -Add the specified user to the group's member list. If the group is neither auditEnabled nor selfserve, then it will use authorize ("update", "{domainName}:group.{groupName}") otherwise membership will be sent for approval to either designated delegates ( in case of auditEnabled groups ) or to domain admins ( in case of selfserve groups ) +Add the specified user to the group's member list. If the group is selfRenewEnabled, then an existing member may extend their expiration time by the configured number of minutes (selfRenewMins) by calling this API regardless or not the user is expired or active. If the group is neither auditEnabled nor selfserve, then it will use authorize ("update", "{domainName}:group.{groupName}") otherwise membership will be sent for approval to either designated delegates ( in case of auditEnabled groups ) or to domain admins ( in case of selfserve groups ) ``` obj = { @@ -660,6 +704,7 @@ obj = { "memberName": "", // name of the user to be added as a member "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. "returnObj": "", // (optional) Return object param updated object back. + "resourceOwner": "", // (optional) Resource owner for the request "membership": "" // Membership object (must contain group/member names as specified in the URI) }; ``` @@ -675,7 +720,8 @@ obj = { "domainName": "", // name of the domain "groupName": "", // name of the group "memberName": "", // name of the user to be removed as a member - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`GroupMemberName `](#groupmembername-string) @@ -721,6 +767,7 @@ obj = { "domainName": "", // name of the domain to be updated "groupName": "", // name of the group "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "detail": "" // GroupMeta object with updated attribute values }; ``` @@ -745,7 +792,7 @@ obj = { ### putGroup(*obj, function(err, json, response) { }); `PUT /domain/{domainName}/group/{groupName}/review` -Review group membership and take action to either extend and/or delete existing members. +Review group membership and take action to either extend and/or delete existing members. The required authorization includes three options: 1. ("update", "{domainName}:group.{groupName}") 2. ("update_members", "{domainName}:group.{groupName}") ``` obj = { @@ -753,6 +800,7 @@ obj = { "groupName": "", // name of the group "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. "returnObj": "", // (optional) Return object param updated object back. + "resourceOwner": "", // (optional) Resource owner for the request "group": "" // Group object with updated and/or deleted members }; ``` @@ -771,6 +819,33 @@ obj = { ``` *Types:* [`EntityName `](#entityname-string) +### putResourceGroupOwnership(*obj, function(err, json, response) { }); + +`PUT /domain/{domainName}/group/{groupName}/ownership` +Set the resource ownership for the given group + +``` +obj = { + "domainName": "", // name of the domain + "groupName": "", // name of the group + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwnership": "" // resource ownership to be set for the given group +}; +``` +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`ResourceGroupOwnership `](#resourcegroupownership-struct) + +### getDomainGroupMembers(*obj, function(err, json, response) { }); + +`GET /domain/{domainName}/group/member` +Get list of principals defined in groups in the given domain + +``` +obj = { + "domainName": "" // name of the domain +}; +``` +*Types:* [`DomainName `](#domainname-string) + ### getPolicyList(*obj, function(err, json, response) { }); `GET /domain/{domainName}/policy` @@ -795,11 +870,11 @@ obj = { "domainName": "", // name of the domain "assertions": "", // return list of assertions in the policy "includeNonActive": "", // include non-active policy versions - "tagKey": "", // (optional) flag to query all policies that have a given tagName - "tagValue": "" // (optional) flag to query all policies that have a given tag name and value + "tagKey": "", // (optional) flag to query all policies that have a given tagName + "tagValue": "" // (optional) flag to query all policies that have a given tag name and value }; ``` -*Types:* [`DomainName `](#domainname-string), [`CompoundName `](#compoundname-string) +*Types:* [`DomainName `](#domainname-string), [`TagKey `](#tagkey-string), [`TagCompoundValue `](#tagcompoundvalue-string) ### getPolicy(*obj, function(err, json, response) { }); @@ -825,6 +900,7 @@ obj = { "policyName": "", // name of the policy to be added/updated "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. "returnObj": "", // (optional) Return object param updated object back. + "resourceOwner": "", // (optional) Resource owner for the request "policy": "" // Policy object to be added or updated in the domain }; ``` @@ -839,7 +915,8 @@ Delete the specified policy. Upon successful completion of this delete request, obj = { "domainName": "", // name of the domain "policyName": "", // name of the policy to be deleted - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string) @@ -868,6 +945,7 @@ obj = { "domainName": "", // name of the domain "policyName": "", // name of the policy "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "assertion": "" // Assertion object to be added to the given policy }; ``` @@ -884,6 +962,7 @@ obj = { "policyName": "", // name of the policy "version": "", // name of the version "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "assertion": "" // Assertion object to be added to the given policy version }; ``` @@ -899,7 +978,8 @@ obj = { "domainName": "", // name of the domain "policyName": "", // name of the policy "assertionId": "", // assertion id - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string) @@ -915,7 +995,8 @@ obj = { "policyName": "", // name of the policy "version": "", // name of the version "assertionId": "", // assertion id - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`SimpleName `](#simplename-string) @@ -931,6 +1012,7 @@ obj = { "policyName": "", // name of the policy "assertionId": "", // assertion id "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "assertionConditions": "" // Assertion conditions object to be added to the given assertion }; ``` @@ -947,6 +1029,7 @@ obj = { "policyName": "", // name of the policy "assertionId": "", // assertion id "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "assertionCondition": "" // Assertion conditions object to be added to the given assertion }; ``` @@ -962,7 +1045,8 @@ obj = { "domainName": "", // name of the domain "policyName": "", // name of the policy "assertionId": "", // assertion id - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string) @@ -978,7 +1062,8 @@ obj = { "policyName": "", // name of the policy "assertionId": "", // assertion id "conditionId": "", // condition id - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string) @@ -1021,7 +1106,8 @@ obj = { "policyName": "", // name of the policy to be added/updated "policyOptions": "", // name of the source version to copy from and name of new version "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. - "returnObj": "" // (optional) Return object param updated object back. + "returnObj": "", // (optional) Return object param updated object back. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`PolicyOptions `](#policyoptions-struct) @@ -1036,7 +1122,8 @@ obj = { "domainName": "", // name of the domain "policyName": "", // name of the policy "policyOptions": "", // name of the version - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`PolicyOptions `](#policyoptions-struct) @@ -1051,11 +1138,27 @@ obj = { "domainName": "", // name of the domain "policyName": "", // name of the policy "version": "", // name of the version to be deleted - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`SimpleName `](#simplename-string) +### putResourcePolicyOwnership(*obj, function(err, json, response) { }); + +`PUT /domain/{domainName}/policy/{policyName}/ownership` +Set the resource ownership for the given policy + +``` +obj = { + "domainName": "", // name of the domain + "policyName": "", // name of the policy + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwnership": "" // resource ownership to be set for the given policy +}; +``` +*Types:* [`DomainName `](#domainname-string), [`EntityName `](#entityname-string), [`ResourcePolicyOwnership `](#resourcepolicyownership-struct) + ### putServiceIdentity(*obj, function(err, json, response) { }); `PUT /domain/{domain}/service/{service}` @@ -1067,6 +1170,7 @@ obj = { "service": "", // name of the service "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. "returnObj": "", // (optional) Return object param updated object back. + "resourceOwner": "", // (optional) Resource owner for the request "detail": "" // ServiceIdentity object to be added/updated in the domain }; ``` @@ -1094,7 +1198,8 @@ Delete the specified ServiceIdentity. Upon successful completion of this delete obj = { "domain": "", // name of the domain "service": "", // name of the service to be deleted - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`SimpleName `](#simplename-string) @@ -1109,11 +1214,11 @@ obj = { "domainName": "", // name of the domain "publickeys": "", // return list of public keys in the service "hosts": "", // return list of hosts in the service - "tagKey": "", // (optional) flag to query all services that have a given tagName - "tagValue": "" // (optional) flag to query all services that have a given tag name and value + "tagKey": "", // (optional) flag to query all services that have a given tagName + "tagValue": "" // (optional) flag to query all services that have a given tag name and value }; ``` -*Types:* [`DomainName `](#domainname-string), [`CompoundName `](#compoundname-string) +*Types:* [`DomainName `](#domainname-string), [`TagKey `](#tagkey-string), [`TagCompoundValue `](#tagcompoundvalue-string) ### getServiceIdentityList(*obj, function(err, json, response) { }); @@ -1154,6 +1259,7 @@ obj = { "service": "", // name of the service "id": "", // the identifier of the public key to be added "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "", // (optional) Resource owner for the request "publicKeyEntry": "" // PublicKeyEntry object to be added/updated in the service }; ``` @@ -1169,7 +1275,8 @@ obj = { "domain": "", // name of the domain "service": "", // name of the service "id": "", // the identifier of the public key to be deleted - "auditRef": "" // (optional) Audit param required(not empty) if domain auditEnabled is true. + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwner": "" // (optional) Resource owner for the request }; ``` *Types:* [`DomainName `](#domainname-string), [`SimpleName `](#simplename-string) @@ -1190,6 +1297,21 @@ obj = { ``` *Types:* [`DomainName `](#domainname-string), [`SimpleName `](#simplename-string), [`ServiceIdentitySystemMeta `](#serviceidentitysystemmeta-struct) +### putResourceServiceIdentityOwnership(*obj, function(err, json, response) { }); + +`PUT /domain/{domainName}/service/{service}/ownership` +Set the resource ownership for the given service + +``` +obj = { + "domainName": "", // name of the domain + "service": "", // name of the service + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "resourceOwnership": "" // resource ownership to be set for the given service +}; +``` +*Types:* [`DomainName `](#domainname-string), [`SimpleName `](#simplename-string), [`ResourceServiceIdentityOwnership `](#resourceserviceidentityownership-struct) + ### putTenancy(*obj, function(err, json, response) { }); `PUT /domain/{domain}/tenancy/{service}` @@ -1674,12 +1796,50 @@ obj = { ``` *Types:* [`ServiceName `](#servicename-string) +### getReviewObjects(*obj, function(err, json, response) { }); + +`GET /review/role` +Fetch all the roles across domains for either the caller or specified principal that require a review based on the last reviewed date and configured attributes. The method requires the caller to be either the principal or authorized in system to carry out the operation for any principal (typically this would be system administrators) 1. authenticated principal is the same as the check principal 2. system authorized ("access", "sys.auth:meta.review.lookup") + +``` +obj = { + "principal": "" // (optional) If not present, will return roles for the user making the call +}; +``` +*Types:* [`ResourceName `](#resourcename-string) + +### getReviewObjects(*obj, function(err, json, response) { }); + +`GET /review/group` +Fetch all the groups across domains for either the caller or specified principal that require a review based on the last reviewed date and configured attributes. The method requires the caller to be either the principal or authorized in system to carry out the operation for any principal (typically this would be system administrators) 1. authenticated principal is the same as the check principal 2. system authorized ("access", "sys.auth:meta.review.lookup") + +``` +obj = { + "principal": "" // (optional) If not present, will return groups for the user making the call +}; +``` +*Types:* [`ResourceName `](#resourcename-string) + ### getInfo(*obj, function(err, json, response) { }); `GET /sys/info` Retrieve the server info. Since we're exposing server version details, the request will require authorization +### putPrincipalState(*obj, function(err, json, response) { }); + +`PUT /principal/{principalName}/state` +Update the state of the principal - currently only the suspended state is supported Suspension can be enforced through the User Authority or by Athenz administrators. The suspended state is used to disable a principal from accessing the Athenz services The required authorization includes the following two options: 1. ("update", "{domainName}:service.{serviceName}") for the domain administrators where the domainName and serviceName are extracted from the principalName 2. ("update", "sys.auth:state.{principalName}") for the Athenz administrators + +``` +obj = { + "principalName": "", // name of the principal + "auditRef": "", // (optional) Audit param required(not empty) if domain auditEnabled is true. + "principalState": "" // Principal state indicating if the principal is suspended or not +}; +``` +*Types:* [`MemberName `](#membername-string), [`PrincipalState `](#principalstate-struct) + ### getRdl.Schema(*obj, function(err, json, response) { }); `GET /schema` @@ -1937,6 +2097,16 @@ A comma separated list of authority keywords } ``` +### TagKey `` + +``` +{ + "type": "String", + "name": "TagKey", + "pattern": "([a-zA-Z0-9_][a-zA-Z0-9_-]*[:\\.])*[a-zA-Z0-9_][a-zA-Z0-9_-]*" +} +``` + ### TagValue `` TagValue to contain generic string patterns @@ -1947,7 +2117,7 @@ TagValue to contain generic string patterns "type": "String", "name": "TagValue", "comment": "TagValue to contain generic string patterns", - "pattern": "[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*" + "pattern": "[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:%,\\/-]*" } ``` @@ -1961,7 +2131,7 @@ A compound value of TagValue "type": "String", "name": "TagCompoundValue", "comment": "A compound value of TagValue", - "pattern": "([a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*\\.)*[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*" + "pattern": "([a-zA-Z0-9_:,\\/][a-zA-Z0-9_:%,\\/-]*\\.)*[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:%,\\/-]*" } ``` @@ -2024,6 +2194,34 @@ A compound value of TagValue } ``` +### ResourceDomainOwnership `` + +The representation of the domain ownership object + + +``` +{ + "type": "Struct", + "name": "ResourceDomainOwnership", + "comment": "The representation of the domain ownership object", + "fields": [ + { + "name": "metaOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's meta attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false +} +``` + ### DomainMeta `` Set of metadata attributes that all domains may have and can be changed. @@ -2111,7 +2309,7 @@ Set of metadata attributes that all domains may have and can be changed. }, { "name": "signAlgorithm", - "type": "SimpleName", + "type": "String", "optional": true, "comment": "rsa or ec signing algorithm to be used for tokens" }, @@ -2169,7 +2367,7 @@ Set of metadata attributes that all domains may have and can be changed. "optional": true, "comment": "key-value pair tags, tag might contain multiple values", "items": "TagValueList", - "keys": "CompoundName" + "keys": "TagKey" }, { "name": "businessService", @@ -2194,6 +2392,44 @@ Set of metadata attributes that all domains may have and can be changed. "type": "Int32", "optional": true, "comment": "features enabled per domain (system attribute)" + }, + { + "name": "contacts", + "type": "Map", + "optional": true, + "comment": "list of domain contacts (PE-Owner, Product-Owner, etc), each type can have a single value", + "items": "String", + "keys": "SimpleName" + }, + { + "name": "environment", + "type": "String", + "optional": true, + "comment": "domain environment e.g. production, staging, etc" + }, + { + "name": "resourceOwnership", + "type": "ResourceDomainOwnership", + "optional": true, + "comment": "ownership information for the domain (read-only attribute)" + }, + { + "name": "x509CertSignerKeyId", + "type": "String", + "optional": true, + "comment": "requested x509 cert signer key id (system attribute)" + }, + { + "name": "sshCertSignerKeyId", + "type": "String", + "optional": true, + "comment": "requested ssh cert signer key id (system attribute)" + }, + { + "name": "slackChannel", + "type": "String", + "optional": true, + "comment": "slack channel for any notifications in this domain" } ], "closed": false @@ -2515,6 +2751,40 @@ An audit log entry for role membership change. } ``` +### ResourceRoleOwnership `` + +The representation of the role ownership object + + +``` +{ + "type": "Struct", + "name": "ResourceRoleOwnership", + "comment": "The representation of the role ownership object", + "fields": [ + { + "name": "metaOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's meta attribute" + }, + { + "name": "membersOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's members attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false +} +``` + ### RoleMeta `` Set of metadata attributes that all roles may have and can be changed by domain admins. @@ -2553,7 +2823,7 @@ Set of metadata attributes that all roles may have and can be changed by domain }, { "name": "signAlgorithm", - "type": "SimpleName", + "type": "String", "optional": true, "comment": "rsa or ec signing algorithm to be used for tokens" }, @@ -2618,7 +2888,7 @@ Set of metadata attributes that all roles may have and can be changed by domain "optional": true, "comment": "key-value pair tags, tag might contain multiple values", "items": "TagValueList", - "keys": "CompoundName" + "keys": "TagKey" }, { "name": "description", @@ -2639,6 +2909,48 @@ Set of metadata attributes that all roles may have and can be changed by domain "optional": true, "comment": "If true, ask for delete confirmation in audit and review enabled roles.", "default": false + }, + { + "name": "lastReviewedDate", + "type": "Timestamp", + "optional": true, + "comment": "last review timestamp of the role" + }, + { + "name": "selfRenew", + "type": "Bool", + "optional": true, + "comment": "Flag indicates whether to allow expired members to renew their membership" + }, + { + "name": "selfRenewMins", + "type": "Int32", + "optional": true, + "comment": "Number of minutes members can renew their membership if self review option is enabled" + }, + { + "name": "maxMembers", + "type": "Int32", + "optional": true, + "comment": "Maximum number of members allowed in the group" + }, + { + "name": "resourceOwnership", + "type": "ResourceRoleOwnership", + "optional": true, + "comment": "ownership information for the role (read-only attribute)" + }, + { + "name": "principalDomainFilter", + "type": "String", + "optional": true, + "comment": "membership filtered based on configured principal domains" + }, + { + "name": "notifyDetails", + "type": "String", + "optional": true, + "comment": "additional details included in the notifications" } ], "closed": false @@ -2694,12 +3006,6 @@ The representation for a Role with set of members. The members (Array` + +The representation of the policy ownership object + + +``` +{ + "type": "Struct", + "name": "ResourcePolicyOwnership", + "comment": "The representation of the policy ownership object", + "fields": [ + { + "name": "assertionsOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's assertions attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false +} +``` + ### Policy `` The representation for a Policy with set of assertions. @@ -3234,7 +3580,13 @@ The representation for a Policy with set of assertions. "optional": true, "comment": "key-value pair tags, tag might contain multiple values", "items": "TagValueList", - "keys": "CompoundName" + "keys": "TagKey" + }, + { + "name": "resourceOwnership", + "type": "ResourcePolicyOwnership", + "optional": true, + "comment": "ownership information for the policy (read-only attribute)" } ], "closed": false @@ -3320,6 +3672,40 @@ The representation of the public key in a service identity object. } ``` +### ResourceServiceIdentityOwnership `` + +The representation of the service identity ownership object + + +``` +{ + "type": "Struct", + "name": "ResourceServiceIdentityOwnership", + "comment": "The representation of the service identity ownership object", + "fields": [ + { + "name": "publicKeysOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's public keys attribute" + }, + { + "name": "hostsOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's host list attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false +} +``` + ### ServiceIdentity `` The representation of the service identity object. @@ -3393,7 +3779,13 @@ The representation of the service identity object. "optional": true, "comment": "key-value pair tags, tag might contain multiple values", "items": "TagValueList", - "keys": "CompoundName" + "keys": "TagKey" + }, + { + "name": "resourceOwnership", + "type": "ResourceServiceIdentityOwnership", + "optional": true, + "comment": "ownership information for the service (read-only attribute)" } ], "closed": false @@ -3613,7 +4005,7 @@ List of template names that is the base struct for server and domain templates }, { "name": "value", - "type": "CompoundName", + "type": "String", "optional": false, "comment": "value of the parameter" } @@ -4219,6 +4611,18 @@ An audit log entry for group membership change. "type": "String", "optional": true, "comment": "for pending membership requests, the request state - e.g. add, delete" + }, + { + "name": "notifyRoles", + "type": "String", + "optional": true, + "comment": "list of roles whose members should be notified for member review/approval/expiry" + }, + { + "name": "notifyDetails", + "type": "String", + "optional": true, + "comment": "additional details included in the notifications" } ], "closed": false @@ -4304,6 +4708,40 @@ The representation for a group membership. } ``` +### ResourceGroupOwnership `` + +The representation of the group ownership object + + +``` +{ + "type": "Struct", + "name": "ResourceGroupOwnership", + "comment": "The representation of the group ownership object", + "fields": [ + { + "name": "metaOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's meta attribute" + }, + { + "name": "membersOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's members attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false +} +``` + ### GroupMeta `` Set of metadata attributes that all groups may have and can be changed by domain admins. @@ -4365,7 +4803,7 @@ Set of metadata attributes that all groups may have and can be changed by domain "optional": true, "comment": "key-value pair tags, tag might contain multiple values", "items": "TagValueList", - "keys": "CompoundName" + "keys": "TagKey" }, { "name": "auditEnabled", @@ -4380,6 +4818,48 @@ Set of metadata attributes that all groups may have and can be changed by domain "optional": true, "comment": "If true, ask for delete confirmation in audit and review enabled groups.", "default": false + }, + { + "name": "lastReviewedDate", + "type": "Timestamp", + "optional": true, + "comment": "last review timestamp of the group" + }, + { + "name": "selfRenew", + "type": "Bool", + "optional": true, + "comment": "Flag indicates whether to allow expired members to renew their membership" + }, + { + "name": "selfRenewMins", + "type": "Int32", + "optional": true, + "comment": "Number of minutes members can renew their membership if self review option is enabled" + }, + { + "name": "maxMembers", + "type": "Int32", + "optional": true, + "comment": "Maximum number of members allowed in the group" + }, + { + "name": "resourceOwnership", + "type": "ResourceGroupOwnership", + "optional": true, + "comment": "ownership information for the group (read-only attribute)" + }, + { + "name": "principalDomainFilter", + "type": "String", + "optional": true, + "comment": "membership filtered based on configured principal domains" + }, + { + "name": "notifyDetails", + "type": "String", + "optional": true, + "comment": "additional details included in the notifications" } ], "closed": false @@ -4422,12 +4902,6 @@ The representation for a Group with set of members. "optional": true, "comment": "an audit log for group membership changes", "items": "GroupAuditLog" - }, - { - "name": "lastReviewedDate", - "type": "Timestamp", - "optional": true, - "comment": "last review timestamp of the group" } ], "closed": false @@ -5486,6 +5960,105 @@ Dependent service provider details } ``` +### ReviewObject `` + +Details for the roles and/or groups that need to be reviewed + + +``` +{ + "type": "Struct", + "name": "ReviewObject", + "comment": "Details for the roles and/or groups that need to be reviewed", + "fields": [ + { + "name": "domainName", + "type": "DomainName", + "optional": false, + "comment": "name of the domain" + }, + { + "name": "name", + "type": "EntityName", + "optional": false, + "comment": "name of the role and/or group" + }, + { + "name": "memberExpiryDays", + "type": "Int32", + "optional": false, + "comment": "all user members in the object have specified max expiry days" + }, + { + "name": "memberReviewDays", + "type": "Int32", + "optional": false, + "comment": "all user members in the object have specified max review days" + }, + { + "name": "serviceExpiryDays", + "type": "Int32", + "optional": false, + "comment": "all services in the object have specified max expiry days" + }, + { + "name": "serviceReviewDays", + "type": "Int32", + "optional": false, + "comment": "all services in the object have specified max review days" + }, + { + "name": "groupExpiryDays", + "type": "Int32", + "optional": false, + "comment": "all groups in the object have specified max expiry days" + }, + { + "name": "groupReviewDays", + "type": "Int32", + "optional": false, + "comment": "all groups in the object have specified max review days" + }, + { + "name": "lastReviewedDate", + "type": "Timestamp", + "optional": true, + "comment": "last review timestamp of the object" + }, + { + "name": "created", + "type": "Timestamp", + "optional": false, + "comment": "creation time of the object" + } + ], + "closed": false +} +``` + +### ReviewObjects `` + +The representation for a list of objects with full details + + +``` +{ + "type": "Struct", + "name": "ReviewObjects", + "comment": "The representation for a list of objects with full details", + "fields": [ + { + "name": "list", + "type": "Array", + "optional": false, + "comment": "list of review objects", + "items": "ReviewObject" + } + ], + "closed": false +} +``` + ### Info `` Copyright The Athenz Authors Licensed under the terms of the Apache version 2.0 license. See LICENSE file for terms. The representation for an info object @@ -5526,6 +6099,52 @@ Copyright The Athenz Authors Licensed under the terms of the Apache version 2.0 } ``` +### PrincipalMember `` + +``` +{ + "type": "Struct", + "name": "PrincipalMember", + "fields": [ + { + "name": "principalName", + "type": "MemberName", + "optional": false, + "comment": "name of the principal" + }, + { + "name": "suspendedState", + "type": "Int32", + "optional": false, + "comment": "current system suspended state of the principal" + } + ], + "closed": false +} +``` + +### PrincipalState `` + +A principal state entry + + +``` +{ + "type": "Struct", + "name": "PrincipalState", + "comment": "A principal state entry", + "fields": [ + { + "name": "suspended", + "type": "Bool", + "optional": false, + "comment": "athenz suspended state for the principal" + } + ], + "closed": false +} +``` + ### rdl.Identifier `` All names need to be of this restricted string type @@ -6506,4 +7125,4 @@ A Schema is a container for types and resources. It is self-contained (no extern ``` -*generated on Wed Sep 27 2023 11:23:58 GMT-0700 (Pacific Daylight Time)* \ No newline at end of file +*generated on Tue Nov 26 2024 15:18:34 GMT+0000 (Greenwich Mean Time)* \ No newline at end of file diff --git a/ui/src/__tests__/components/settings/__snapshots__/SettingTable.test.js.snap b/ui/src/__tests__/components/settings/__snapshots__/SettingTable.test.js.snap index acd7638ab7e..0ea1489b22e 100644 --- a/ui/src/__tests__/components/settings/__snapshots__/SettingTable.test.js.snap +++ b/ui/src/__tests__/components/settings/__snapshots__/SettingTable.test.js.snap @@ -1243,6 +1243,47 @@ exports[`SettingTable should render setting table 1`] = ` Maximum number of members allowed in the role + + + Domain Filter + + +
+
+ +
+
+
+ + + Membership filtered based on configured principal domains + + `; diff --git a/ui/src/__tests__/pages/domain/[domain]/group/[group]/__snapshots__/settings.test.js.snap b/ui/src/__tests__/pages/domain/[domain]/group/[group]/__snapshots__/settings.test.js.snap index 271cb1f8270..f8e34e5a79c 100644 --- a/ui/src/__tests__/pages/domain/[domain]/group/[group]/__snapshots__/settings.test.js.snap +++ b/ui/src/__tests__/pages/domain/[domain]/group/[group]/__snapshots__/settings.test.js.snap @@ -1067,7 +1067,7 @@ exports[`GroupSettingPage should render 1`] = ` vertical-align: text-bottom; } -.emotion-179 { +.emotion-192 { padding-bottom: 20px; display: flex; -webkit-box-pack: justify; @@ -1083,7 +1083,7 @@ exports[`GroupSettingPage should render 1`] = ` flex-flow: row nowrap; } -.emotion-181 { +.emotion-194 { border: none; border-radius: 2px; box-shadow: 0 0 0 1px #3697f2 inset; @@ -1108,25 +1108,25 @@ exports[`GroupSettingPage should render 1`] = ` color: #3697f2; } -.emotion-181:first-of-type { +.emotion-194:first-of-type { margin-left: 0; } -.emotion-181:disabled { +.emotion-194:disabled { background: rgba(48,48,48,0.1); color: rgba(48,48,48,0.2); cursor: not-allowed; } -.emotion-181:disabled { +.emotion-194:disabled { box-shadow: 0 0 0 1px rgba(48,48,48,0.1) inset; } -.emotion-181:hover:not(:disabled) { +.emotion-194:hover:not(:disabled) { background: #d7e2fd; } -.emotion-183 { +.emotion-196 { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -1149,13 +1149,13 @@ exports[`GroupSettingPage should render 1`] = ` width: 20px; } -.emotion-185 { +.emotion-198 { fill: #303030; cursor: inherit; vertical-align: text-bottom; } -.emotion-186 { +.emotion-199 { margin-right: 0; border-left: 1px solid #d5d5d5; -webkit-flex: 0 0 350px; @@ -1170,7 +1170,7 @@ exports[`GroupSettingPage should render 1`] = ` width: 350px; } -.emotion-188 { +.emotion-201 { -webkit-align-items: baseline; -webkit-box-align: baseline; -ms-flex-align: baseline; @@ -1186,38 +1186,38 @@ exports[`GroupSettingPage should render 1`] = ` padding: 20px 30px 20px 15px; } -.emotion-190 { +.emotion-203 { font-size: 16px; font-weight: 600; } -.emotion-192 { +.emotion-205 { color: #3570f4; -webkit-text-decoration: none; text-decoration: none; cursor: pointer; } -.emotion-194 { +.emotion-207 { padding: 0 5px; color: #d5d5d5; } -.emotion-198 { +.emotion-211 { padding: 0 30px 0 15px; } -.emotion-200 { +.emotion-213 { padding: 10px 0; display: flex; } -.emotion-202 { +.emotion-215 { font-size: 1.25em; margin-right: 5px; } -.emotion-204 { +.emotion-217 { fill: #303030; cursor: inherit; vertical-align: baseline; @@ -1939,20 +1939,61 @@ exports[`GroupSettingPage should render 1`] = ` Maximum number of members allowed in the group + + + Domain Filter + + +
+
+ +
+
+
+ + + Membership filtered based on configured principal domains + +
@@ -1965,11 +2006,11 @@ exports[`GroupSettingPage should render 1`] = ` data-testid="user-domains" >
athens.ci diff --git a/ui/src/__tests__/pages/domain/[domain]/role/[role]/__snapshots__/settings.test.js.snap b/ui/src/__tests__/pages/domain/[domain]/role/[role]/__snapshots__/settings.test.js.snap index 56ed61620dc..2b3f3d9b26c 100644 --- a/ui/src/__tests__/pages/domain/[domain]/role/[role]/__snapshots__/settings.test.js.snap +++ b/ui/src/__tests__/pages/domain/[domain]/role/[role]/__snapshots__/settings.test.js.snap @@ -1067,7 +1067,7 @@ exports[`SettingPage should render 1`] = ` vertical-align: text-bottom; } -.emotion-270 { +.emotion-283 { padding-bottom: 20px; display: flex; -webkit-box-pack: justify; @@ -1083,7 +1083,7 @@ exports[`SettingPage should render 1`] = ` flex-flow: row nowrap; } -.emotion-272 { +.emotion-285 { border: none; border-radius: 2px; box-shadow: 0 0 0 1px #3697f2 inset; @@ -1108,25 +1108,25 @@ exports[`SettingPage should render 1`] = ` color: #3697f2; } -.emotion-272:first-of-type { +.emotion-285:first-of-type { margin-left: 0; } -.emotion-272:disabled { +.emotion-285:disabled { background: rgba(48,48,48,0.1); color: rgba(48,48,48,0.2); cursor: not-allowed; } -.emotion-272:disabled { +.emotion-285:disabled { box-shadow: 0 0 0 1px rgba(48,48,48,0.1) inset; } -.emotion-272:hover:not(:disabled) { +.emotion-285:hover:not(:disabled) { background: #d7e2fd; } -.emotion-274 { +.emotion-287 { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -1149,13 +1149,13 @@ exports[`SettingPage should render 1`] = ` width: 20px; } -.emotion-276 { +.emotion-289 { fill: #303030; cursor: inherit; vertical-align: text-bottom; } -.emotion-277 { +.emotion-290 { margin-right: 0; border-left: 1px solid #d5d5d5; -webkit-flex: 0 0 350px; @@ -1170,7 +1170,7 @@ exports[`SettingPage should render 1`] = ` width: 350px; } -.emotion-279 { +.emotion-292 { -webkit-align-items: baseline; -webkit-box-align: baseline; -ms-flex-align: baseline; @@ -1186,38 +1186,38 @@ exports[`SettingPage should render 1`] = ` padding: 20px 30px 20px 15px; } -.emotion-281 { +.emotion-294 { font-size: 16px; font-weight: 600; } -.emotion-283 { +.emotion-296 { color: #3570f4; -webkit-text-decoration: none; text-decoration: none; cursor: pointer; } -.emotion-285 { +.emotion-298 { padding: 0 5px; color: #d5d5d5; } -.emotion-289 { +.emotion-302 { padding: 0 30px 0 15px; } -.emotion-291 { +.emotion-304 { padding: 10px 0; display: flex; } -.emotion-293 { +.emotion-306 { font-size: 1.25em; margin-right: 5px; } -.emotion-295 { +.emotion-308 { fill: #303030; cursor: inherit; vertical-align: baseline; @@ -2238,20 +2238,61 @@ exports[`SettingPage should render 1`] = ` Maximum number of members allowed in the role + + + Domain Filter + + +
+
+ +
+
+
+ + + Membership filtered based on configured principal domains + +
@@ -2264,11 +2305,11 @@ exports[`SettingPage should render 1`] = ` data-testid="user-domains" >
athens.ci diff --git a/ui/src/__tests__/spec/tests/groups.spec.js b/ui/src/__tests__/spec/tests/groups.spec.js index f0339ad51c1..1cd833b4a44 100644 --- a/ui/src/__tests__/spec/tests/groups.spec.js +++ b/ui/src/__tests__/spec/tests/groups.spec.js @@ -15,6 +15,7 @@ */ const reviewExtendTest = 'review-extend-test'; +const domainFilterTest = 'domain-filter-test'; const TEST_NAME_GROUP_HISTORY_VISIBLE_AFTER_REFRESH = 'group history should be visible when navigating to it and after page refresh'; @@ -236,4 +237,100 @@ describe('group screen tests', () => { // to reset currentTest after running cleanup currentTest = ''; }); + + it('Domain Filter - only principals matching specific domain(s) can be added to a group', async () => { + // open browser + await browser.newUser(); + await browser.url(`/domain/athenz.dev.functional-test/group`); + + // open add group modal + let addGroupButton = await $('button*=Add Group'); + await addGroupButton.click(); + // add group name + await $('#group-name-input').addValue(domainFilterTest); + // submit + let submitButton = await $('button*=Submit'); + await submitButton.click(); + + // specify unix domain in settings + // open settings + await $( + `.//*[local-name()="svg" and @id="group-settings-icon-${domainFilterTest}"]` + ).click(); + // add unix domain + let principalDomainFilter = await $('#setting-principalDomainFilter'); + await principalDomainFilter.addValue('unix'); + // submit + await $('button*=Submit').click(); + await $('button[data-testid="update-modal-update"]').click(); + + // attempt to add non-unix user + await $('div*=Members').click(); + await $('button*=Add Member').click(); + let memberInput = await $('input[name="member-name"]'); + let nonUnixUser = 'user.aporss'; + await memberInput.addValue(nonUnixUser); + await $(`div*=${nonUnixUser}`).click(); + // submit + await $('button*=Submit').click(); + // verify fail message + errorMessage = await $('div[data-testid="error-message"]'); + expect(await errorMessage.getText()).toBe( + `Status: 400. Message: Principal ${nonUnixUser} is not allowed for the group` + ); + // since unix domain was specified in domain filter + // unix user is valid to be added + // add unix user + let clearInput = await $( + `.//*[local-name()="svg" and @data-wdio="clear-input"]` + ); + clearInput.click(); + let unix = 'unix.yahoo'; + await memberInput.addValue(unix); + await $(`div*=${unix}`).click(); + // submit + await $('button*=Submit').click(); + // check unix user was added + memberRow = await $(`tr[data-wdio='${unix}-member-row']`).$( + `td*=${unix}` + ); + await expect(memberRow).toHaveTextContaining(unix); + + // specify user domain to be able to add non-unix user + await $('div*=Settings').click(); + principalDomainFilter = await $('#setting-principalDomainFilter'); + await principalDomainFilter.clearValue(); + // append user domain to unix domain + await principalDomainFilter.addValue('unix,user'); + // submit + await $('button*=Submit').click(); + await $('button[data-testid="update-modal-update"]').click(); + + // add non-unix user + await $('div*=Members').click(); + await $('button*=Add Member').click(); + memberInput = await $('input[name="member-name"]'); + await memberInput.addValue(nonUnixUser); + await $(`div*=${nonUnixUser}`).click(); + // submit + await $('button*=Submit').click(); + // check non-unix user was added + memberRow = await $(`tr[data-wdio='${nonUnixUser}-member-row']`).$( + `td*=${nonUnixUser}` + ); + await expect(memberRow).toHaveTextContaining(nonUnixUser); + }); + + // delete group created in previous test + after(async () => { + // delete group created in previous test + await browser.newUser(); + await browser.url(`/domain/athenz.dev.functional-test/group`); + await expect(browser).toHaveUrlContaining('athenz'); + + await $( + `.//*[local-name()="svg" and @id="delete-group-icon-${domainFilterTest}"]` + ).click(); + await $('button*=Delete').click(); + }); }); diff --git a/ui/src/__tests__/spec/tests/roles.spec.js b/ui/src/__tests__/spec/tests/roles.spec.js index 0730062b0df..262691dc1f4 100644 --- a/ui/src/__tests__/spec/tests/roles.spec.js +++ b/ui/src/__tests__/spec/tests/roles.spec.js @@ -16,6 +16,7 @@ const dropdownTestRoleName = 'dropdown-test-role'; const reviewExtendTest = 'review-extend-test'; +const domainFilterTest = 'domain-filter-test'; const TEST_NAME_HISTORY_VISIBLE_AFTER_PAGE_REFRESH = 'role history should be visible when navigating to it and after page refresh'; @@ -41,8 +42,8 @@ describe('role screen tests', () => { // ADD test role // open Add Role screen - let addiRoleButton = await $('button*=Add Role'); - await addiRoleButton.click(); + let addRoleButton = await $('button*=Add Role'); + await addRoleButton.click(); // add group info let inputRoleName = await $('#role-name-input'); let roleName = 'history-test-role'; @@ -554,4 +555,105 @@ describe('role screen tests', () => { // reset current test currentTest = ''; }); + + it('Domain Filter - only principals matching specific domain(s) can be added to a role', async () => { + // open browser + await browser.newUser(); + await browser.url(`/domain/athenz.dev.functional-test/role`); + + // open add role modal + let addiRoleButton = await $('button*=Add Role'); + await addiRoleButton.click(); + // add role name + let inputRoleName = await $('#role-name-input'); + await inputRoleName.addValue(domainFilterTest); + // specify domain + let advancedSettingsIcon = await $('#advanced-settings-icon'); + await advancedSettingsIcon.click(); + let principalDomainFilter = await $('#setting-principalDomainFilter'); + await principalDomainFilter.addValue('athenz'); + // attempt to submit a member that doesn't belong to specified domain + // add user + const user = 'user.aporss'; + let memberInput = await $('input[name="member-name"]'); + await memberInput.addValue(user); + let dropdownOption = await $(`div*=${user}`); + await dropdownOption.click(); + // submit + let submitButton = await $('button*=Submit'); + await submitButton.click(); + // verify fail message + let errorMessage = await $('div[data-testid="error-message"]'); + expect(await errorMessage.getText()).toBe( + `Status: 400. Message: Principal ${user} is not allowed for the role` + ); + // change to specified domain + await principalDomainFilter.clearValue(); + await principalDomainFilter.addValue('user'); + // submit - success + await submitButton.click(); + // view role members + await $( + `.//*[local-name()="svg" and @data-wdio="${domainFilterTest}-view-members"]` + ).click(); + // verify member was added to the role + let memberRow = await $(`tr[data-wdio='${user}-member-row']`).$( + `td*=${user}` + ); + await expect(memberRow).toHaveTextContaining(user); + + // check that domain filter applies to an existing role + // let's reuse the role created above + await $('button*=Add Member').click(); + // attempt to add unix user + const unix = 'unix.yahoo'; + memberInput = await $('input[name="member-name"]'); + await memberInput.addValue(unix); + await $(`div*=${unix}`).click(); + // submit + await $('button*=Submit').click(); + // verify fail message - unix domain is not registered in the filter yet + errorMessage = await $('div[data-testid="error-message"]'); + expect(await errorMessage.getText()).toBe( + `Status: 400. Message: Principal ${unix} is not allowed for the role` + ); + // close modal + await $('button*=Cancel').click(); + + // let's add unix user to domain filter in role settings + await $('div*=Settings').click(); + principalDomainFilter = await $('#setting-principalDomainFilter'); + await principalDomainFilter.clearValue(); + await principalDomainFilter.addValue('user,unix'); + // submit + await $('button*=Submit').click(); + await $('button[data-testid="update-modal-update"]').click(); + + // now it must be possible to add member of a unix domain + // add unix user + await $('div*=Members').click(); + await $('button*=Add Member').click(); + await $('input[name="member-name"]').addValue(unix); + await $(`div*=${unix}`).click(); + // submit + await $('button*=Submit').click(); + // check new member was added + memberRow = await $(`tr[data-wdio='${unix}-member-row']`).$( + `td*=${unix}` + ); + await expect(memberRow).toHaveTextContaining(unix); + }); + + // delete role created in previous test + after(async () => { + // delete role created in previous test + await browser.newUser(); + await browser.url(`/domain/athenz.dev.functional-test/role`); + await expect(browser).toHaveUrlContaining('athenz'); + + await $( + `.//*[local-name()="svg" and @id="${domainFilterTest}-delete-role-button"]` + ).click(); + await $('button*=Delete').click(); + }); }); diff --git a/ui/src/__tests__/spec/wdio.conf.js b/ui/src/__tests__/spec/wdio.conf.js index cd82b7063ba..d8e9b763329 100644 --- a/ui/src/__tests__/spec/wdio.conf.js +++ b/ui/src/__tests__/spec/wdio.conf.js @@ -270,7 +270,7 @@ let config = { mochaOpts: { ui: 'bdd', timeout: 60000, - retries: 2, + retries: 0, }, // // ===== diff --git a/ui/src/components/constants/constants.js b/ui/src/components/constants/constants.js index ad3bbdc4eeb..db81c14f6be 100644 --- a/ui/src/components/constants/constants.js +++ b/ui/src/components/constants/constants.js @@ -175,6 +175,8 @@ export const SELF_RENEW_MINS_DESC = 'Number of minutes members can renew their membership if self review option is enabled'; export const ADD_ROLE_MAX_MEMBERS_DESC = 'Maximum number of members allowed in the role'; +export const GROUP_ROLE_DOMAIN_FILTER_DESC = + 'Membership filtered based on configured principal domains'; export const ADD_ROLE_MEMBER_EXPIRY_DAYS_DESC = 'All user members in the role will have specified max expiry days'; export const ADD_ROLE_MEMBER_REVIEW_DAYS_DESC = diff --git a/ui/src/components/role/AddRoleAdvancedSettings.js b/ui/src/components/role/AddRoleAdvancedSettings.js index 988da6c0654..340390e6fa9 100644 --- a/ui/src/components/role/AddRoleAdvancedSettings.js +++ b/ui/src/components/role/AddRoleAdvancedSettings.js @@ -37,6 +37,7 @@ import { ADD_ROLE_SELF_RENEW_DESC, SELF_RENEW_MINS_DESC, ADD_ROLE_MAX_MEMBERS_DESC, + GROUP_ROLE_DOMAIN_FILTER_DESC, } from '../constants/constants'; import SettingRow from '../settings/SettingRow'; @@ -307,6 +308,17 @@ export default class AddRoleAdvancedSettings extends React.Component { inModal={true} disabled={this.props.delegated} />, + , ]; } } diff --git a/ui/src/components/settings/SettingTable.js b/ui/src/components/settings/SettingTable.js index d406cdcdbc3..b329738fd13 100644 --- a/ui/src/components/settings/SettingTable.js +++ b/ui/src/components/settings/SettingTable.js @@ -24,6 +24,7 @@ import _ from 'lodash'; import { ADD_GROUP_DELETE_PROTECTION_DESC, ADD_ROLE_DELETE_PROTECTION_DESC, + GROUP_ROLE_DOMAIN_FILTER_DESC, MODAL_TIME_OUT, SELF_RENEW_MINS_DESC, } from '../constants/constants'; @@ -188,6 +189,10 @@ class SettingTable extends React.Component { collection.selfRenewMins === undefined ? '' : collection.selfRenewMins.toString(), + principalDomainFilter: + collection.principalDomainFilter === undefined + ? '' + : collection.principalDomainFilter.toString(), }; return collectionDetails; } @@ -257,6 +262,8 @@ class SettingTable extends React.Component { if (this.props.category === 'role') { collectionMeta = this.state.copyCollectionDetails; + collectionMeta.principalDomainFilter = + this.state.copyCollectionDetails.principalDomainFilter; } else if (this.props.category === 'group') { collectionMeta.auditEnabled = this.state.copyCollectionDetails.auditEnabled; @@ -280,6 +287,8 @@ class SettingTable extends React.Component { this.state.copyCollectionDetails.deleteProtection; collectionMeta.maxMembers = this.state.copyCollectionDetails.maxMembers; + collectionMeta.principalDomainFilter = + this.state.copyCollectionDetails.principalDomainFilter; } else if (this.props.category === 'domain') { collectionMeta.memberExpiryDays = this.state.copyCollectionDetails.memberExpiryDays; @@ -739,6 +748,24 @@ class SettingTable extends React.Component { /> ); + (this.props.category === 'role' || this.props.category === 'group') && + rows.push( + + ); + return this.props.isLoading.length !== 0 ? ( ) : ( diff --git a/ui/src/config/msd.json b/ui/src/config/msd.json index ac3ce502454..605046e6ccc 100644 --- a/ui/src/config/msd.json +++ b/ui/src/config/msd.json @@ -116,6 +116,34 @@ "pattern": "\\*|([a-zA-Z0-9_][a-zA-Z0-9_-]*\\.)*[a-zA-Z0-9_][a-zA-Z0-9_-]*" } }, + { + "StringTypeDef": { + "type": "String", + "name": "StaticWorkloadComponent", + "pattern": "[a-zA-Z0-9][a-zA-Z0-9-:._]*" + } + }, + { + "StringTypeDef": { + "type": "String", + "name": "StaticWorkloadFQDN", + "pattern": "([a-zA-Z0-9][a-zA-Z0-9-:._]*\\.)*[a-zA-Z0-9][a-zA-Z0-9-:._]*" + } + }, + { + "StringTypeDef": { + "type": "String", + "name": "StaticWorkloadName", + "pattern": "(([a-zA-Z0-9][a-zA-Z0-9-:._]*\\.)*[a-zA-Z0-9][a-zA-Z0-9-:._]*)(\\/[0-9]{1,3})?" + } + }, + { + "StringTypeDef": { + "type": "String", + "name": "TransportPolicySubjectExternal", + "pattern": "(([a-zA-Z0-9][a-zA-Z0-9-:._]*\\.)*[a-zA-Z0-9][a-zA-Z0-9-:._]*)(\\/[0-9]{1,3})?" + } + }, { "EnumTypeDef": { "type": "Enum", @@ -217,6 +245,40 @@ "type": "TransportPolicySubjectServiceName", "optional": false, "comment": "Name of the service" + }, + { + "name": "externalPeer", + "type": "TransportPolicySubjectExternal", + "optional": true, + "comment": "External peer ( not in Athenz )" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "TransportPolicySubjectSelectorRequirement", + "comment": "A subject selector requirement is a selector that contains value, a key, and an operator that relates the key and value.", + "fields": [ + { + "name": "key", + "type": "String", + "optional": false, + "comment": "key that the selector applies to" + }, + { + "name": "operator", + "type": "String", + "optional": false, + "comment": "Operator that is applied to the key and value" + }, + { + "name": "value", + "type": "String", + "optional": false, + "comment": "Value that the selector applies to" } ], "closed": false @@ -247,6 +309,13 @@ "optional": true, "comment": "Scope of transport policy", "items": "TransportPolicyScope" + }, + { + "name": "additionalConditions", + "type": "Array", + "optional": true, + "comment": "List of any additional conditions", + "items": "TransportPolicySubjectSelectorRequirement" } ], "closed": false @@ -372,6 +441,12 @@ "optional": false, "comment": "Assertion id associated with this transport policy" }, + { + "name": "identifier", + "type": "EntityName", + "optional": true, + "comment": "Policy Identifier" + }, { "name": "lastModified", "type": "Timestamp", @@ -406,6 +481,12 @@ "optional": false, "comment": "Assertion id associated with this transport policy" }, + { + "name": "identifier", + "type": "EntityName", + "optional": true, + "comment": "Policy Identifier" + }, { "name": "lastModified", "type": "Timestamp", @@ -535,6 +616,62 @@ "closed": false } }, + { + "StructTypeDef": { + "type": "Struct", + "name": "TransportPolicyRequest", + "comment": "Input to create a transport policy", + "fields": [ + { + "name": "direction", + "type": "TransportPolicyTrafficDirection", + "optional": false, + "comment": "Direction of network traffic" + }, + { + "name": "identifier", + "type": "EntityName", + "optional": false, + "comment": "Policy Identifier" + }, + { + "name": "subject", + "type": "TransportPolicySubject", + "optional": false, + "comment": "Subject for the policy" + }, + { + "name": "conditions", + "type": "Array", + "optional": true, + "comment": "List of transport policy conditions", + "items": "TransportPolicyCondition" + }, + { + "name": "sourcePorts", + "type": "Array", + "optional": false, + "comment": "List of source network traffic ports", + "items": "TransportPolicyPort" + }, + { + "name": "destinationPorts", + "type": "Array", + "optional": false, + "comment": "List of destination network traffic ports", + "items": "TransportPolicyPort" + }, + { + "name": "peers", + "type": "Array", + "optional": true, + "comment": "Source or destination of the policy depending on direction", + "items": "TransportPolicySubject" + } + ], + "closed": false + } + }, { "EnumTypeDef": { "type": "Enum", @@ -675,7 +812,7 @@ }, { "name": "name", - "type": "String", + "type": "StaticWorkloadName", "optional": true, "comment": "name associated with the workload. In most cases will be a FQDN" }, @@ -779,11 +916,154 @@ "closed": false } }, + { + "StructTypeDef": { + "type": "Struct", + "name": "DomainServices", + "comment": "request type to search all workloads for a domain and selected list of its services", + "fields": [ + { + "name": "domainName", + "type": "DomainName", + "optional": false, + "comment": "name of the domain" + }, + { + "name": "serviceNames", + "type": "Array", + "optional": false, + "comment": "list of service names", + "items": "EntityName" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "BulkWorkloadRequest", + "comment": "request type to search all workloads for a list of services grouped by domains", + "fields": [ + { + "name": "domainServices", + "type": "Array", + "optional": false, + "comment": "list of services, grouped by domain", + "items": "DomainServices" + }, + { + "name": "fetchStaticTypeWorkloads", + "type": "Bool", + "optional": true, + "comment": "whether to fetch static type workloads", + "default": true + }, + { + "name": "fetchDynamicTypeWorkloads", + "type": "Bool", + "optional": true, + "comment": "whether to fetch dynamic type workloads", + "default": true + }, + { + "name": "applicableStaticTypes", + "type": "Array", + "optional": true, + "comment": "list of applicable static workload types, if not set then that means all. Applicable only if fetchStaticTypeWorkloads is enabled", + "items": "StaticWorkloadType" + }, + { + "name": "resolveStaticWorkloads", + "type": "Bool", + "optional": true, + "comment": "resolve static workloads to IPs, if applicable", + "default": false + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "BulkWorkloadResponse", + "comment": "response of a bulk workload search request", + "fields": [ + { + "name": "unmodifiedServices", + "type": "Array", + "optional": false, + "comment": "list of services grouped by domain, those are not changed since time stamp in matchingTag", + "items": "DomainServices" + }, + { + "name": "workloads", + "type": "Workloads", + "optional": false, + "comment": "matching workloads" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "CompositeInstance", + "comment": "generic instance", + "fields": [ + { + "name": "domainName", + "type": "DomainName", + "optional": false, + "comment": "name of the domain" + }, + { + "name": "serviceName", + "type": "EntityName", + "optional": false, + "comment": "name of the service" + }, + { + "name": "instance", + "type": "SimpleName", + "optional": false, + "comment": "instance name/id" + }, + { + "name": "instanceType", + "type": "String", + "optional": true, + "comment": "instance type" + }, + { + "name": "provider", + "type": "String", + "optional": true, + "comment": "name of the instance provider, for example aws/gcp" + }, + { + "name": "certExpiryTime", + "type": "Timestamp", + "optional": true, + "comment": "certificate expiry time (ex: getNotAfter), if applicable" + }, + { + "name": "certIssueTime", + "type": "Timestamp", + "optional": true, + "comment": "certificate issue time (ex: getNotBefore), if applicable" + } + ], + "closed": false + } + }, { "EnumTypeDef": { "type": "Enum", "name": "NetworkPolicyChangeEffect", - "comment": "IMPACT indicates that a change in network policy will interfere with workings of one or more transport policies NO_IMAPCT indicates that a change in network policy will not interfere with workings of any transport policy", + "comment": "IMPACT indicates that a change in network policy will interfere with workings of one or more transport policies NO_IMPACT indicates that a change in network policy will not interfere with workings of any transport policy", "elements": [ { "symbol": "IMPACT" @@ -932,44 +1212,340 @@ } }, { - "StringTypeDef": { - "type": "String", - "name": "rdl.Identifier", - "comment": "All names need to be of this restricted string type", - "pattern": "[a-zA-Z_]+[a-zA-Z_0-9]*" - } - }, - { - "StringTypeDef": { - "type": "String", - "name": "rdl.NamespacedIdentifier", - "comment": "A Namespace is a dotted compound name, using reverse domain name order (i.e. \"com.yahoo.auth\")", - "pattern": "([a-zA-Z_]+[a-zA-Z_0-9]*)(\\.[a-zA-Z_]+[a-zA-Z_0-9])*" - } - }, - { - "EnumTypeDef": { - "type": "Enum", - "name": "rdl.BaseType", - "elements": [ - { - "symbol": "Bool" - }, + "StructTypeDef": { + "type": "Struct", + "name": "KubernetesLabelSelectorRequirement", + "comment": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.", + "fields": [ { - "symbol": "Int8" + "name": "key", + "type": "String", + "optional": false, + "comment": "Label key that the selector applies to" }, { - "symbol": "Int16" + "name": "operator", + "type": "String", + "optional": false, + "comment": "Operator that is applied to the key. Valid operators are In, NotIn, Exists and DoesNotExist." }, { - "symbol": "Int32" - }, + "name": "values", + "type": "Array", + "optional": true, + "comment": "Array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.", + "items": "String" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "KubernetesLabelSelector", + "comment": "A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects.", + "fields": [ { - "symbol": "Int64" + "name": "matchExpressions", + "type": "Array", + "optional": false, + "comment": "Array of label selector requirements. The requirements are ANDed.", + "items": "KubernetesLabelSelectorRequirement" }, { - "symbol": "Float32" - }, + "name": "matchLabels", + "type": "Map", + "optional": false, + "comment": "Map of label key/value pairs", + "items": "String", + "keys": "String" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "PolicyPort", + "name": "KubernetesNetworkPolicyPort", + "comment": "Kubernetes network policy port range", + "fields": [ + { + "name": "protocol", + "type": "TransportPolicyProtocol", + "optional": false, + "comment": "Network policy protocol. Allowed values: TCP, UDP." + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "KubernetesIPBlock", + "comment": "Kubernetes network policy IP block source/target", + "fields": [ + { + "name": "cidr", + "type": "String", + "optional": false, + "comment": "CIDR block representing IP range for source/target" + }, + { + "name": "except", + "type": "Array", + "optional": true, + "comment": "Exception for CIDR blocks, if needed", + "items": "String" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "KubernetesNetworkPolicyPeer", + "comment": "Kubernetes network policy peer (source/target)", + "fields": [ + { + "name": "podSelector", + "type": "KubernetesLabelSelector", + "optional": true, + "comment": "Kubernetes pod selector for the network policy source/target" + }, + { + "name": "namespaceSelector", + "type": "KubernetesLabelSelector", + "optional": true, + "comment": "Kubernetes namespace selector for the network policy source/target" + }, + { + "name": "ipBlock", + "type": "KubernetesIPBlock", + "optional": true, + "comment": "IP block for the network policy source/target" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "KubernetesNetworkPolicyIngressRule", + "comment": "Kubernetes network policy ingress rule", + "fields": [ + { + "name": "from", + "type": "Array", + "optional": true, + "comment": "Network policy source, when empty all sources are allowed", + "items": "KubernetesNetworkPolicyPeer" + }, + { + "name": "ports", + "type": "Array", + "optional": true, + "comment": "Ingress port(s), when empty all ports are allowed", + "items": "KubernetesNetworkPolicyPort" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "KubernetesNetworkPolicyEgressRule", + "comment": "Kubernetes network policy egress rule", + "fields": [ + { + "name": "to", + "type": "Array", + "optional": true, + "comment": "Network policy target, when empty all sources are allowed", + "items": "KubernetesNetworkPolicyPeer" + }, + { + "name": "ports", + "type": "Array", + "optional": true, + "comment": "Egress port(s), when empty all ports are allowed", + "items": "KubernetesNetworkPolicyPort" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "KubernetesNetworkPolicySpec", + "comment": "Kubernetes network policy spec", + "fields": [ + { + "name": "podSelector", + "type": "KubernetesLabelSelector", + "optional": false, + "comment": "Kubernetes pod selector for the network policy target" + }, + { + "name": "policyTypes", + "type": "Array", + "optional": false, + "comment": "Network policy types - Ingress, Egress", + "items": "String" + }, + { + "name": "ingress", + "type": "Array", + "optional": true, + "comment": "Ingress network policy rules, if empty then all ingress traffic is blocked", + "items": "KubernetesNetworkPolicyIngressRule" + }, + { + "name": "egress", + "type": "Array", + "optional": true, + "comment": "Egress network policy rules, if empty then all egress traffic is blocked", + "items": "KubernetesNetworkPolicyEgressRule" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "KubernetesNetworkPolicyRequest", + "comment": "Request object containing Kubernetes network policy inputs", + "fields": [ + { + "name": "athenzDomainLabel", + "type": "String", + "optional": true, + "comment": "Label key name used on pods to identify Athenz domain" + }, + { + "name": "athenzServiceLabel", + "type": "String", + "optional": false, + "comment": "Label key name used on pods to identify Athenz service" + }, + { + "name": "networkPolicyType", + "type": "String", + "optional": true, + "comment": "Network policy type, default is vanilla Kubernetes" + }, + { + "name": "requestedApiVersion", + "type": "String", + "optional": true, + "comment": "Requested network policy apiVersion" + }, + { + "name": "networkPolicyNamespace", + "type": "String", + "optional": true, + "comment": "Kubernetes namespace for the network policy object" + }, + { + "name": "domainLabelAsNamespaceSelector", + "type": "Bool", + "optional": true, + "comment": "Use athenzDomainLabel as namespace selector", + "default": false + }, + { + "name": "domainInServiceLabel", + "type": "Bool", + "optional": true, + "comment": "Use Athenz domain name in service label", + "default": false + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "KubernetesNetworkPolicyResponse", + "comment": "Response object containing Kubernetes network policy", + "fields": [ + { + "name": "apiVersion", + "type": "String", + "optional": false, + "comment": "Kubernetes network policy apiVersion" + }, + { + "name": "kind", + "type": "String", + "optional": false, + "comment": "Kubernetes network policy kind" + }, + { + "name": "metadata", + "type": "Map", + "optional": false, + "comment": "Kubernetes network policy metadata", + "items": "String", + "keys": "String" + }, + { + "name": "spec", + "type": "KubernetesNetworkPolicySpec", + "optional": false, + "comment": "Kubernetes network policy spec" + } + ], + "closed": false + } + }, + { + "StringTypeDef": { + "type": "String", + "name": "rdl.Identifier", + "comment": "All names need to be of this restricted string type", + "pattern": "[a-zA-Z_]+[a-zA-Z_0-9]*" + } + }, + { + "StringTypeDef": { + "type": "String", + "name": "rdl.NamespacedIdentifier", + "comment": "A Namespace is a dotted compound name, using reverse domain name order (i.e. \"com.yahoo.auth\")", + "pattern": "([a-zA-Z_]+[a-zA-Z_0-9]*)(\\.[a-zA-Z_]+[a-zA-Z_0-9])*" + } + }, + { + "EnumTypeDef": { + "type": "Enum", + "name": "rdl.BaseType", + "elements": [ + { + "symbol": "Bool" + }, + { + "symbol": "Int8" + }, + { + "symbol": "Int16" + }, + { + "symbol": "Int32" + }, + { + "symbol": "Int64" + }, + { + "symbol": "Float32" + }, { "symbol": "Float64" }, @@ -1822,12 +2398,12 @@ "type": "TransportPolicyValidationRequest", "method": "POST", "path": "/transportpolicy/validate", - "comment": "API to validate microsegmentation policies against network policies", + "comment": "API to validate micro-segmentation policies against network policies", "inputs": [ { "name": "transportPolicy", "type": "TransportPolicyValidationRequest", - "comment": "Struct representing microsegmentation policy entered by the user", + "comment": "Struct representing micro-segmentation policy entered by the user", "pathParam": false, "optional": false, "flag": false @@ -1928,7 +2504,9 @@ } ], "auth": { - "authenticate": true + "authenticate": false, + "action": "msd.GetNetworkPolicy", + "resource": "{domainName}:domain" }, "expected": "OK", "exceptions": { @@ -1951,9 +2529,10 @@ "name": "getTransportPolicyRulesByDomain" }, { - "type": "Workloads", - "method": "GET", - "path": "/domain/{domainName}/service/{serviceName}/workloads", + "type": "TransportPolicyRequest", + "method": "PUT", + "path": "/domain/{domainName}/service/{serviceName}/transportpolicy", + "comment": "This API endpoint facilitates the creation or update of a transport policy for a specified domain and service. It is designed exclusively for the purpose of creating or updating transport policies, and does not support mixed-case scenarios. Once a transport policy is established, the destination service, protocol, and both source and destination ports become non-editable. To modify any of these fields, it is necessary to create a new policy and delete the old one.", "inputs": [ { "name": "domainName", @@ -1966,34 +2545,44 @@ { "name": "serviceName", "type": "EntityName", - "comment": "name of the service", + "comment": "Name of the service", "pathParam": true, "optional": false, "flag": false }, { - "name": "matchingTag", + "name": "auditRef", "type": "String", - "comment": "Retrieved from the previous request, this timestamp specifies to the server to return any workloads modified since this time", + "comment": "Audit param required(not empty) if domain auditEnabled is true.", "pathParam": false, - "header": "If-None-Match", + "header": "Y-Audit-Ref", "optional": true, "flag": false - } - ], - "outputs": [ + }, { - "name": "tag", + "name": "resourceOwner", "type": "String", - "header": "ETag", - "comment": "The current latest modification timestamp is returned in this header", - "optional": false + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, + { + "name": "payload", + "type": "TransportPolicyRequest", + "comment": "Struct representing input transport policy", + "pathParam": false, + "optional": false, + "flag": false } ], "auth": { - "authenticate": true + "authenticate": false, + "action": "msd.UpdateNetworkPolicy", + "resource": "{domainName}:service.{serviceName}" }, - "expected": "OK", + "expected": "NO_CONTENT", "exceptions": { "TOO_MANY_REQUESTS": { "type": "ResourceError" @@ -2011,12 +2600,218 @@ "type": "ResourceError" } }, - "name": "getWorkloadsByService" + "name": "putTransportPolicy" }, { - "type": "Workloads", + "type": "TransportPolicyRules", "method": "GET", - "path": "/workloads/{ip}", + "path": "/domain/{domainName}/service/{serviceName}/transportpolicies", + "comment": "API endpoint to get the transport policy rules defined in Athenz for a given domain and service", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "serviceName", + "type": "EntityName", + "comment": "Name of the service", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "matchingTag", + "type": "String", + "comment": "Retrieved from the previous request, this timestamp specifies to the server to return any policies modified since this time", + "pathParam": false, + "header": "If-None-Match", + "optional": true, + "flag": false + } + ], + "outputs": [ + { + "name": "tag", + "type": "String", + "header": "ETag", + "comment": "The current latest modification timestamp is returned in this header", + "optional": false + } + ], + "auth": { + "authenticate": false, + "action": "msd.GetNetworkPolicy", + "resource": "{domainName}:service.{serviceName}" + }, + "expected": "OK", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + }, + "name": "getTransportPolicyRulesByService" + }, + { + "type": "TransportPolicyRules", + "method": "DELETE", + "path": "/domain/{domainName}/service/{serviceName}/transportpolicy/{id}", + "comment": "API endpoint to delete the transport policy Upon successful completion of this delete request, the server will return NO_CONTENT status code without any data (no object will be returned).", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "Name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "serviceName", + "type": "EntityName", + "comment": "Name of the service", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "id", + "type": "Int64", + "comment": "Id of the assertion representing the transport policy", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "auditRef", + "type": "String", + "comment": "Audit param required(not empty) if domain auditEnabled is true.", + "pathParam": false, + "header": "Y-Audit-Ref", + "optional": true, + "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + } + ], + "auth": { + "authenticate": false, + "action": "msd.DeleteNetworkPolicy", + "resource": "{domainName}:service.{serviceName}" + }, + "expected": "NO_CONTENT", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "CONFLICT": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + }, + "name": "deleteTransportPolicy" + }, + { + "type": "Workloads", + "method": "GET", + "path": "/domain/{domainName}/service/{serviceName}/workloads", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "serviceName", + "type": "EntityName", + "comment": "name of the service", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "matchingTag", + "type": "String", + "comment": "Retrieved from the previous request, this timestamp specifies to the server to return any workloads modified since this time", + "pathParam": false, + "header": "If-None-Match", + "optional": true, + "flag": false + } + ], + "outputs": [ + { + "name": "tag", + "type": "String", + "header": "ETag", + "comment": "The current latest modification timestamp is returned in this header", + "optional": false + } + ], + "auth": { + "authenticate": true + }, + "expected": "OK", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + }, + "name": "getWorkloadsByService" + }, + { + "type": "Workloads", + "method": "GET", + "path": "/workloads/{ip}", "inputs": [ { "name": "ip", @@ -2097,6 +2892,15 @@ "pathParam": false, "optional": false, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -2151,6 +2955,15 @@ "pathParam": true, "optional": false, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -2207,6 +3020,15 @@ "pathParam": false, "optional": false, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -2258,11 +3080,20 @@ }, { "name": "name", - "type": "String", + "type": "StaticWorkloadName", "comment": "name associated with the workload. In most cases will be a FQDN", "pathParam": true, "optional": false, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -2392,6 +3223,192 @@ }, "name": "getWorkloadsByDomain" }, + { + "type": "BulkWorkloadRequest", + "method": "POST", + "path": "/workloads", + "comment": "Read only endpoint to fetch workloads for a list of services grouped by domains", + "inputs": [ + { + "name": "request", + "type": "BulkWorkloadRequest", + "comment": "workload search request", + "pathParam": false, + "optional": false, + "flag": false + }, + { + "name": "matchingTag", + "type": "String", + "comment": "Retrieved from the previous request, this timestamp specifies to the server to return any workloads modified since this time", + "pathParam": false, + "header": "If-None-Match", + "optional": true, + "flag": false + } + ], + "outputs": [ + { + "name": "tag", + "type": "String", + "header": "ETag", + "comment": "The current latest modification timestamp is returned in this header", + "optional": false + } + ], + "auth": { + "authenticate": true + }, + "expected": "OK", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + }, + "name": "getWorkloadsByDomainAndService" + }, + { + "type": "CompositeInstance", + "method": "PUT", + "path": "/domain/{domainName}/service/{serviceName}/workload/discover/instance", + "comment": "Api to discover an additional instance which can have static or dynamic or both IPs", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "serviceName", + "type": "EntityName", + "comment": "name of the service", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "instance", + "type": "CompositeInstance", + "comment": "Generic instance", + "pathParam": false, + "optional": false, + "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + } + ], + "auth": { + "authenticate": false, + "action": "update", + "resource": "{domainName}:service.{serviceName}" + }, + "expected": "NO_CONTENT", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + }, + "name": "putCompositeInstance" + }, + { + "type": "Workloads", + "method": "DELETE", + "path": "/domain/{domainName}/service/{serviceName}/workload/discover/instance/{instance}", + "comment": "Api to delete an additional instance which can have static or dynamic or both IPs", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "serviceName", + "type": "EntityName", + "comment": "name of the service", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "instance", + "type": "SimpleName", + "comment": "instance name/id/key", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + } + ], + "auth": { + "authenticate": false, + "action": "update", + "resource": "{domainName}:service.{serviceName}" + }, + "expected": "NO_CONTENT", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + }, + "name": "deleteCompositeInstance" + }, { "type": "NetworkPolicyChangeImpactRequest", "method": "POST", @@ -2430,6 +3447,79 @@ }, "name": "evaluateNetworkPolicyChange" }, + { + "type": "KubernetesNetworkPolicyRequest", + "method": "POST", + "path": "/domain/{domainName}/service/{serviceName}/kubernetesnetworkpolicy", + "comment": "API endpoint to get the Kubernetes network policy converted from the corresponding MSD policy", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "Name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "serviceName", + "type": "EntityName", + "comment": "Name of the service", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "request", + "type": "KubernetesNetworkPolicyRequest", + "comment": "Struct representing input options based on the cluster context", + "pathParam": false, + "optional": false, + "flag": false + }, + { + "name": "matchingTag", + "type": "String", + "comment": "Retrieved from the previous request, this timestamp specifies to the server to return any policies modified since this time", + "pathParam": false, + "header": "If-None-Match", + "optional": true, + "flag": false + } + ], + "outputs": [ + { + "name": "tag", + "type": "String", + "header": "ETag", + "comment": "The current latest modification timestamp is returned in this header", + "optional": false + } + ], + "auth": { + "authenticate": false, + "action": "msd.GetNetworkPolicy", + "resource": "{domainName}:service.{serviceName}" + }, + "expected": "OK", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + } + }, { "type": "rdl.Schema", "method": "GET", @@ -2441,4 +3531,4 @@ "expected": "OK" } ] -} +} \ No newline at end of file diff --git a/ui/src/config/ums.json b/ui/src/config/ums.json index 82ec3a94e58..737aa3daace 100644 --- a/ui/src/config/ums.json +++ b/ui/src/config/ums.json @@ -300,7 +300,31 @@ "type": "String", "name": "ClusterInfo", "comment": "Cluster info", - "pattern": "[a-z0-9][a-z0-9-]*" + "pattern": "[a-z0-9][a-z0-9.]*[a-z0-9-]*" + } + }, + { + "StringTypeDef": { + "type": "String", + "name": "TagValue", + "comment": "Tag Value", + "pattern": "[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*" + } + }, + { + "StringTypeDef": { + "type": "String", + "name": "TagCompoundValue", + "comment": "Tag Compound Value", + "pattern": "([a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*\\.)*[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*" + } + }, + { + "StringTypeDef": { + "type": "String", + "name": "RestrictToValue", + "comment": "Restrict To tag value", + "pattern": "([a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*\\.)*[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*" } }, { @@ -332,6 +356,12 @@ { "symbol": "SSH_IN_SUDO_RR" }, + { + "symbol": "SSH_IN_PUSHSHELL" + }, + { + "symbol": "SSH_IN_NOLOGIN" + }, { "symbol": "LOCAL" } @@ -355,6 +385,38 @@ ] } }, + { + "EnumTypeDef": { + "type": "Enum", + "name": "Environment", + "elements": [ + { + "symbol": "def" + }, + { + "symbol": "development" + }, + { + "symbol": "integration" + }, + { + "symbol": "qa" + }, + { + "symbol": "staging" + }, + { + "symbol": "sandbox" + }, + { + "symbol": "production" + }, + { + "symbol": "productionExpiryOptional" + } + ] + } + }, { "StructTypeDef": { "type": "Struct", @@ -506,6 +568,12 @@ "optional": false, "comment": "list of users in the groups", "items": "EntityName" + }, + { + "name": "systemGroup", + "type": "Bool", + "optional": true, + "comment": "flag indicating it's a system group or not" } ], "closed": false @@ -778,6 +846,12 @@ "comment": "used only for mapping of unix group to roles for unix groups", "items": "UserRole" }, + { + "name": "systemGroup", + "type": "Bool", + "optional": true, + "comment": "used only for unix group, indicating it's a system group or not" + }, { "name": "sshTouchless", "type": "Bool", @@ -998,6 +1072,20 @@ "comment": "List of headless roles", "items": "HeadlessRole" }, + { + "name": "environment", + "type": "Environment", + "optional": true, + "comment": "Environment for the profile", + "default": "def" + }, + { + "name": "elevatedClearance", + "type": "Bool", + "optional": true, + "comment": "If true, all roles in the profile will have elevated clearance", + "default": false + }, { "name": "sshStrict", "type": "Bool", @@ -1160,7 +1248,13 @@ "name": "text", "type": "String", "optional": false, - "comment": "Text describes the error" + "comment": "Text describes the error in detail" + }, + { + "name": "title", + "type": "String", + "optional": true, + "comment": "Short description of error" }, { "name": "stdout", @@ -1201,6 +1295,14 @@ "type": "Timestamp", "optional": true, "comment": "timestamp of the error last reported by Calypso CLI" + }, + { + "name": "metadata", + "type": "Map", + "optional": true, + "comment": "Metadata of the host sent by calypso CLI", + "items": "String", + "keys": "String" } ], "closed": false @@ -1380,6 +1482,15 @@ "queryParam": "hostname", "optional": true, "flag": false + }, + { + "name": "restrictTo", + "type": "RestrictToValue", + "comment": "restrictTo tag values will be used for retrieving members", + "pathParam": false, + "queryParam": "restrictTo", + "optional": true, + "flag": false } ], "auth": { @@ -1571,7 +1682,7 @@ { "name": "deleteAllRoles", "type": "Bool", - "comment": "If true, delete all Athenz roles associate with this profile", + "comment": "If true, all roles used in the profile will be deleted. If false, only roles with prefix ums.. will be deleted", "pathParam": false, "queryParam": "deleteAllRoles", "optional": false, @@ -2672,4 +2783,4 @@ } } ] -} +} \ No newline at end of file diff --git a/ui/src/config/zms.json b/ui/src/config/zms.json index b2aa4888854..a892ebe11ad 100644 --- a/ui/src/config/zms.json +++ b/ui/src/config/zms.json @@ -159,7 +159,7 @@ "type": "String", "name": "TagValue", "comment": "TagValue to contain generic string patterns", - "pattern": "[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*" + "pattern": "[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:%,\\/-]*" } }, { @@ -167,7 +167,7 @@ "type": "String", "name": "TagCompoundValue", "comment": "A compound value of TagValue", - "pattern": "([a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*\\.)*[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:,\\/-]*" + "pattern": "([a-zA-Z0-9_:,\\/][a-zA-Z0-9_:%,\\/-]*\\.)*[a-zA-Z0-9_:,\\/][a-zA-Z0-9_:%,\\/-]*" } }, { @@ -214,6 +214,28 @@ "pattern": "([a-zA-Z0-9\\*][a-zA-Z0-9_\\.\\*-]*,)*[a-zA-Z0-9\\*][a-zA-Z0-9_\\.\\*-]*" } }, + { + "StructTypeDef": { + "type": "Struct", + "name": "ResourceDomainOwnership", + "comment": "The representation of the domain ownership object", + "fields": [ + { + "name": "metaOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's meta attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false + } + }, { "StructTypeDef": { "type": "Struct", @@ -393,6 +415,30 @@ "type": "String", "optional": true, "comment": "domain environment e.g. production, staging, etc" + }, + { + "name": "resourceOwnership", + "type": "ResourceDomainOwnership", + "optional": true, + "comment": "ownership information for the domain (read-only attribute)" + }, + { + "name": "x509CertSignerKeyId", + "type": "String", + "optional": true, + "comment": "requested x509 cert signer key id (system attribute)" + }, + { + "name": "sshCertSignerKeyId", + "type": "String", + "optional": true, + "comment": "requested ssh cert signer key id (system attribute)" + }, + { + "name": "slackChannel", + "type": "String", + "optional": true, + "comment": "slack channel for any notifications in this domain" } ], "closed": false @@ -668,6 +714,34 @@ "closed": false } }, + { + "StructTypeDef": { + "type": "Struct", + "name": "ResourceRoleOwnership", + "comment": "The representation of the role ownership object", + "fields": [ + { + "name": "metaOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's meta attribute" + }, + { + "name": "membersOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's members attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false + } + }, { "StructTypeDef": { "type": "Struct", @@ -811,6 +885,24 @@ "type": "Int32", "optional": true, "comment": "Maximum number of members allowed in the group" + }, + { + "name": "resourceOwnership", + "type": "ResourceRoleOwnership", + "optional": true, + "comment": "ownership information for the role (read-only attribute)" + }, + { + "name": "principalDomainFilter", + "type": "String", + "optional": true, + "comment": "membership filtered based on configured principal domains" + }, + { + "name": "notifyDetails", + "type": "String", + "optional": true, + "comment": "additional details included in the notifications" } ], "closed": false @@ -1055,6 +1147,18 @@ "type": "ResourceName", "optional": true, "comment": "name of the role that handles the membership delegation for the role specified in roleName" + }, + { + "name": "notifyRoles", + "type": "String", + "optional": true, + "comment": "list of roles whose members should be notified for member review/approval/expiry" + }, + { + "name": "notifyDetails", + "type": "String", + "optional": true, + "comment": "additional details included in the notifications" } ], "closed": false @@ -1264,6 +1368,28 @@ "closed": false } }, + { + "StructTypeDef": { + "type": "Struct", + "name": "ResourcePolicyOwnership", + "comment": "The representation of the policy ownership object", + "fields": [ + { + "name": "assertionsOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's assertions attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false + } + }, { "StructTypeDef": { "type": "Struct", @@ -1320,6 +1446,12 @@ "comment": "key-value pair tags, tag might contain multiple values", "items": "TagValueList", "keys": "TagKey" + }, + { + "name": "resourceOwnership", + "type": "ResourcePolicyOwnership", + "optional": true, + "comment": "ownership information for the policy (read-only attribute)" } ], "closed": false @@ -1386,6 +1518,34 @@ "closed": false } }, + { + "StructTypeDef": { + "type": "Struct", + "name": "ResourceServiceIdentityOwnership", + "comment": "The representation of the service identity ownership object", + "fields": [ + { + "name": "publicKeysOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's public keys attribute" + }, + { + "name": "hostsOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's host list attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false + } + }, { "StructTypeDef": { "type": "Struct", @@ -1455,6 +1615,12 @@ "comment": "key-value pair tags, tag might contain multiple values", "items": "TagValueList", "keys": "TagKey" + }, + { + "name": "resourceOwnership", + "type": "ResourceServiceIdentityOwnership", + "optional": true, + "comment": "ownership information for the service (read-only attribute)" } ], "closed": false @@ -2148,6 +2314,18 @@ "type": "String", "optional": true, "comment": "for pending membership requests, the request state - e.g. add, delete" + }, + { + "name": "notifyRoles", + "type": "String", + "optional": true, + "comment": "list of roles whose members should be notified for member review/approval/expiry" + }, + { + "name": "notifyDetails", + "type": "String", + "optional": true, + "comment": "additional details included in the notifications" } ], "closed": false @@ -2226,6 +2404,34 @@ "closed": false } }, + { + "StructTypeDef": { + "type": "Struct", + "name": "ResourceGroupOwnership", + "comment": "The representation of the group ownership object", + "fields": [ + { + "name": "metaOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's meta attribute" + }, + { + "name": "membersOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object's members attribute" + }, + { + "name": "objectOwner", + "type": "SimpleName", + "optional": true, + "comment": "owner of the object itself - checked for object deletion" + } + ], + "closed": false + } + }, { "StructTypeDef": { "type": "Struct", @@ -2321,6 +2527,24 @@ "type": "Int32", "optional": true, "comment": "Maximum number of members allowed in the group" + }, + { + "name": "resourceOwnership", + "type": "ResourceGroupOwnership", + "optional": true, + "comment": "ownership information for the group (read-only attribute)" + }, + { + "name": "principalDomainFilter", + "type": "String", + "optional": true, + "comment": "membership filtered based on configured principal domains" + }, + { + "name": "notifyDetails", + "type": "String", + "optional": true, + "comment": "additional details included in the notifications" } ], "closed": false @@ -3370,6 +3594,43 @@ "closed": false } }, + { + "StructTypeDef": { + "type": "Struct", + "name": "PrincipalMember", + "fields": [ + { + "name": "principalName", + "type": "MemberName", + "optional": false, + "comment": "name of the principal" + }, + { + "name": "suspendedState", + "type": "Int32", + "optional": false, + "comment": "current system suspended state of the principal" + } + ], + "closed": false + } + }, + { + "StructTypeDef": { + "type": "Struct", + "name": "PrincipalState", + "comment": "A principal state entry", + "fields": [ + { + "name": "suspended", + "type": "Bool", + "optional": false, + "comment": "athenz suspended state for the principal" + } + ], + "closed": false + } + }, { "StringTypeDef": { "type": "String", @@ -4417,6 +4678,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "detail", "type": "TopLevelDomain", @@ -4470,6 +4740,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "detail", "type": "SubDomain", @@ -4526,6 +4805,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "detail", "type": "UserDomain", @@ -4581,6 +4869,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -4637,6 +4934,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -4683,6 +4989,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -4732,6 +5047,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "detail", "type": "DomainMeta", @@ -5188,10 +5512,10 @@ } }, { - "type": "DomainDataCheck", - "method": "GET", - "path": "/domain/{domainName}/check", - "comment": "Carry out data check operation for the specified domain.", + "type": "ResourceDomainOwnership", + "method": "PUT", + "path": "/domain/{domainName}/ownership", + "comment": "Set the resource ownership for the given domain", "inputs": [ { "name": "domainName", @@ -5200,12 +5524,31 @@ "pathParam": true, "optional": false, "flag": false + }, + { + "name": "auditRef", + "type": "String", + "comment": "Audit param required(not empty) if domain auditEnabled is true.", + "pathParam": false, + "header": "Y-Audit-Ref", + "optional": true, + "flag": false + }, + { + "name": "resourceOwnership", + "type": "ResourceDomainOwnership", + "comment": "resource ownership to be set for the given domain", + "pathParam": false, + "optional": false, + "flag": false } ], "auth": { - "authenticate": true + "authenticate": false, + "action": "update", + "resource": "{domainName}:meta.domain.ownership" }, - "expected": "OK", + "expected": "NO_CONTENT", "exceptions": { "TOO_MANY_REQUESTS": { "type": "ResourceError" @@ -5213,6 +5556,9 @@ "UNAUTHORIZED": { "type": "ResourceError" }, + "BAD_REQUEST": { + "type": "ResourceError" + }, "NOT_FOUND": { "type": "ResourceError" }, @@ -5222,10 +5568,44 @@ } }, { - "type": "Entity", - "method": "PUT", - "path": "/domain/{domainName}/entity/{entityName}", - "comment": "Put an entity into the domain.", + "type": "DomainDataCheck", + "method": "GET", + "path": "/domain/{domainName}/check", + "comment": "Carry out data check operation for the specified domain.", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + } + ], + "auth": { + "authenticate": true + }, + "expected": "OK", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + } + }, + { + "type": "Entity", + "method": "PUT", + "path": "/domain/{domainName}/entity/{entityName}", + "comment": "Put an entity into the domain.", "inputs": [ { "name": "domainName", @@ -5659,6 +6039,15 @@ "flag": false, "default": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "role", "type": "Role", @@ -5725,6 +6114,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -5998,6 +6396,15 @@ "flag": false, "default": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "membership", "type": "Membership", @@ -6070,6 +6477,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -6325,6 +6741,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "detail", "type": "RoleMeta", @@ -6437,7 +6862,7 @@ "type": "Role", "method": "PUT", "path": "/domain/{domainName}/role/{roleName}/review", - "comment": "Review role membership and take action to either extend and/or delete existing members.", + "comment": "Review role membership and take action to either extend and/or delete existing members. The required authorization includes two options: 1. (\"update\", \"{domainName}:role.{roleName}\") 2. (\"update_members\", \"{domainName}:role.{roleName}\")", "inputs": [ { "name": "domainName", @@ -6474,6 +6899,15 @@ "flag": false, "default": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "role", "type": "Role", @@ -6484,9 +6918,7 @@ } ], "auth": { - "authenticate": false, - "action": "update", - "resource": "{domainName}:role.{roleName}" + "authenticate": true }, "expected": "NO_CONTENT", "exceptions": { @@ -6511,6 +6943,70 @@ }, "name": "PutRoleReview" }, + { + "type": "ResourceRoleOwnership", + "method": "PUT", + "path": "/domain/{domainName}/role/{roleName}/ownership", + "comment": "Set the resource ownership for the given role", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "roleName", + "type": "EntityName", + "comment": "name of the role", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "auditRef", + "type": "String", + "comment": "Audit param required(not empty) if domain auditEnabled is true.", + "pathParam": false, + "header": "Y-Audit-Ref", + "optional": true, + "flag": false + }, + { + "name": "resourceOwnership", + "type": "ResourceRoleOwnership", + "comment": "resource ownership to be set for the given role", + "pathParam": false, + "optional": false, + "flag": false + } + ], + "auth": { + "authenticate": false, + "action": "update", + "resource": "{domainName}:meta.role.ownership.{roleName}" + }, + "expected": "NO_CONTENT", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + } + }, { "type": "Groups", "method": "GET", @@ -6679,6 +7175,15 @@ "flag": false, "default": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "group", "type": "Group", @@ -6745,6 +7250,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -6933,6 +7447,15 @@ "flag": false, "default": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "membership", "type": "GroupMembership", @@ -7005,6 +7528,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -7204,6 +7736,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "detail", "type": "GroupMeta", @@ -7318,7 +7859,7 @@ "type": "Group", "method": "PUT", "path": "/domain/{domainName}/group/{groupName}/review", - "comment": "Review group membership and take action to either extend and/or delete existing members.", + "comment": "Review group membership and take action to either extend and/or delete existing members. The required authorization includes three options: 1. (\"update\", \"{domainName}:group.{groupName}\") 2. (\"update_members\", \"{domainName}:group.{groupName}\")", "inputs": [ { "name": "domainName", @@ -7355,6 +7896,15 @@ "flag": false, "default": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "group", "type": "Group", @@ -7365,9 +7915,7 @@ } ], "auth": { - "authenticate": false, - "action": "update", - "resource": "{domainName}:group.{groupName}" + "authenticate": true }, "expected": "NO_CONTENT", "exceptions": { @@ -7440,6 +7988,107 @@ }, "name": "getPendingDomainGroupMembersList" }, + { + "type": "ResourceGroupOwnership", + "method": "PUT", + "path": "/domain/{domainName}/group/{groupName}/ownership", + "comment": "Set the resource ownership for the given group", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "groupName", + "type": "EntityName", + "comment": "name of the group", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "auditRef", + "type": "String", + "comment": "Audit param required(not empty) if domain auditEnabled is true.", + "pathParam": false, + "header": "Y-Audit-Ref", + "optional": true, + "flag": false + }, + { + "name": "resourceOwnership", + "type": "ResourceGroupOwnership", + "comment": "resource ownership to be set for the given group", + "pathParam": false, + "optional": false, + "flag": false + } + ], + "auth": { + "authenticate": false, + "action": "update", + "resource": "{domainName}:meta.group.ownership.{groupName}" + }, + "expected": "NO_CONTENT", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + } + }, + { + "type": "DomainGroupMembers", + "method": "GET", + "path": "/domain/{domainName}/group/member", + "comment": "Get list of principals defined in groups in the given domain", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + } + ], + "auth": { + "authenticate": true + }, + "expected": "OK", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + } + }, { "type": "PolicyList", "method": "GET", @@ -7653,6 +8302,15 @@ "flag": false, "default": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "policy", "type": "Policy", @@ -7712,11 +8370,20 @@ "flag": false }, { - "name": "auditRef", + "name": "auditRef", + "type": "String", + "comment": "Audit param required(not empty) if domain auditEnabled is true.", + "pathParam": false, + "header": "Y-Audit-Ref", + "optional": true, + "flag": false + }, + { + "name": "resourceOwner", "type": "String", - "comment": "Audit param required(not empty) if domain auditEnabled is true.", + "comment": "Resource owner for the request", "pathParam": false, - "header": "Y-Audit-Ref", + "header": "Athenz-Resource-Owner", "optional": true, "flag": false } @@ -7832,6 +8499,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "assertion", "type": "Assertion", @@ -7907,6 +8583,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "assertion", "type": "Assertion", @@ -7982,6 +8667,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -8057,6 +8751,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -8126,6 +8829,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "assertionConditions", "type": "AssertionConditions", @@ -8201,6 +8913,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "assertionCondition", "type": "AssertionCondition", @@ -8275,6 +8996,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -8350,6 +9080,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -8527,6 +9266,15 @@ "optional": true, "flag": false, "default": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -8595,6 +9343,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -8663,6 +9420,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -8693,6 +9459,70 @@ }, "name": "deletePolicyVersion" }, + { + "type": "ResourcePolicyOwnership", + "method": "PUT", + "path": "/domain/{domainName}/policy/{policyName}/ownership", + "comment": "Set the resource ownership for the given policy", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "policyName", + "type": "EntityName", + "comment": "name of the policy", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "auditRef", + "type": "String", + "comment": "Audit param required(not empty) if domain auditEnabled is true.", + "pathParam": false, + "header": "Y-Audit-Ref", + "optional": true, + "flag": false + }, + { + "name": "resourceOwnership", + "type": "ResourcePolicyOwnership", + "comment": "resource ownership to be set for the given policy", + "pathParam": false, + "optional": false, + "flag": false + } + ], + "auth": { + "authenticate": false, + "action": "update", + "resource": "{domainName}:meta.policy.ownership.{policyName}" + }, + "expected": "NO_CONTENT", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + } + }, { "type": "ServiceIdentity", "method": "PUT", @@ -8734,6 +9564,15 @@ "flag": false, "default": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "detail", "type": "ServiceIdentity", @@ -8845,6 +9684,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -9093,6 +9941,15 @@ "optional": true, "flag": false }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false + }, { "name": "publicKeyEntry", "type": "PublicKeyEntry", @@ -9167,6 +10024,15 @@ "header": "Y-Audit-Ref", "optional": true, "flag": false + }, + { + "name": "resourceOwner", + "type": "String", + "comment": "Resource owner for the request", + "pathParam": false, + "header": "Athenz-Resource-Owner", + "optional": true, + "flag": false } ], "auth": { @@ -9271,6 +10137,70 @@ } } }, + { + "type": "ResourceServiceIdentityOwnership", + "method": "PUT", + "path": "/domain/{domainName}/service/{service}/ownership", + "comment": "Set the resource ownership for the given service", + "inputs": [ + { + "name": "domainName", + "type": "DomainName", + "comment": "name of the domain", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "service", + "type": "SimpleName", + "comment": "name of the service", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "auditRef", + "type": "String", + "comment": "Audit param required(not empty) if domain auditEnabled is true.", + "pathParam": false, + "header": "Y-Audit-Ref", + "optional": true, + "flag": false + }, + { + "name": "resourceOwnership", + "type": "ResourceServiceIdentityOwnership", + "comment": "resource ownership to be set for the given service", + "pathParam": false, + "optional": false, + "flag": false + } + ], + "auth": { + "authenticate": false, + "action": "update", + "resource": "{domainName}:meta.service.ownership.{service}" + }, + "expected": "NO_CONTENT", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + } + }, { "type": "Tenancy", "method": "PUT", @@ -11296,6 +12226,63 @@ } } }, + { + "type": "PrincipalState", + "method": "PUT", + "path": "/principal/{principalName}/state", + "comment": "Update the state of the principal - currently only the suspended state is supported Suspension can be enforced through the User Authority or by Athenz administrators. The suspended state is used to disable a principal from accessing the Athenz services The required authorization includes the following two options: 1. (\"update\", \"{domainName}:service.{serviceName}\") for the domain administrators where the domainName and serviceName are extracted from the principalName 2. (\"update\", \"sys.auth:state.{principalName}\") for the Athenz administrators", + "inputs": [ + { + "name": "principalName", + "type": "MemberName", + "comment": "name of the principal", + "pathParam": true, + "optional": false, + "flag": false + }, + { + "name": "auditRef", + "type": "String", + "comment": "Audit param required(not empty) if domain auditEnabled is true.", + "pathParam": false, + "header": "Y-Audit-Ref", + "optional": true, + "flag": false + }, + { + "name": "principalState", + "type": "PrincipalState", + "comment": "Principal state indicating if the principal is suspended or not", + "pathParam": false, + "optional": false, + "flag": false + } + ], + "auth": { + "authenticate": true + }, + "expected": "NO_CONTENT", + "exceptions": { + "TOO_MANY_REQUESTS": { + "type": "ResourceError" + }, + "CONFLICT": { + "type": "ResourceError" + }, + "UNAUTHORIZED": { + "type": "ResourceError" + }, + "BAD_REQUEST": { + "type": "ResourceError" + }, + "NOT_FOUND": { + "type": "ResourceError" + }, + "FORBIDDEN": { + "type": "ResourceError" + } + } + }, { "type": "rdl.Schema", "method": "GET", @@ -11307,4 +12294,4 @@ "expected": "OK" } ] -} +} \ No newline at end of file diff --git a/ui/src/config/zts.json b/ui/src/config/zts.json index 24ad4d64eb9..cf9c2fb59b5 100644 --- a/ui/src/config/zts.json +++ b/ui/src/config/zts.json @@ -4053,6 +4053,16 @@ "optional": false, "flag": false, "default": false + }, + { + "name": "service", + "type": "ServiceName", + "comment": "service", + "pathParam": false, + "queryParam": "service", + "optional": false, + "flag": false, + "default": "zts" } ], "expected": "OK", @@ -4208,6 +4218,16 @@ "optional": false, "flag": false, "default": false + }, + { + "name": "allScopePresent", + "type": "Bool", + "comment": "flag to indicate that all requested roles/groups in the scope must be present in the response otherwise return an error", + "pathParam": false, + "queryParam": "allScopePresent", + "optional": false, + "flag": false, + "default": false } ], "outputs": [ @@ -4531,4 +4551,4 @@ "expected": "OK" } ] -} +} \ No newline at end of file