{
  "description": "ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider.",
  "properties": {
    "apiVersion": {
      "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
      "type": "string"
    },
    "kind": {
      "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
      "type": "string"
    },
    "metadata": {
      "type": "object"
    },
    "spec": {
      "description": "Spec for configuring the identity provider.",
      "properties": {
        "bind": {
          "description": "Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server\nto be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt.",
          "properties": {
            "secretName": {
              "description": "SecretName contains the name of a namespace-local Secret object that provides the username and\npassword for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be\nof type \"kubernetes.io/basic-auth\" which includes \"username\" and \"password\" keys. The username value\nshould be the full dn (distinguished name) of your bind account, e.g. \"cn=bind-account,ou=users,dc=example,dc=com\".\nThe password must be non-empty.",
              "minLength": 1,
              "type": "string"
            }
          },
          "required": [
            "secretName"
          ],
          "type": "object",
          "additionalProperties": false
        },
        "groupSearch": {
          "description": "GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory.",
          "properties": {
            "attributes": {
              "description": "Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as\nthe result of the group search.",
              "properties": {
                "groupName": {
                  "description": "GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name\nin the user's list of groups after a successful authentication.\nThe value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory\nserver in the user's entry. E.g. \"cn\" for common name. Distinguished names can be used by specifying lower-case \"dn\".\nOptional. When not specified, this defaults to a custom field that looks like \"sAMAccountName@domain\",\nwhere domain is constructed from the domain components of the group DN.",
                  "type": "string"
                }
              },
              "type": "object",
              "additionalProperties": false
            },
            "base": {
              "description": "Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g.\n\"ou=groups,dc=example,dc=com\".\nOptional, when not specified it will be based on the result of a query for the defaultNamingContext\n(see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).\nThe default behavior searches your entire domain for groups.\nIt may make sense to specify a subtree as a search base if you wish to exclude some groups\nfor security reasons or to make searches faster.",
              "type": "string"
            },
            "filter": {
              "description": "Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user.\nThe pattern \"{}\" must occur in the filter at least once and will be dynamically replaced by the\nvalue of an attribute of the user entry found as a result of the user search. Which attribute's\nvalue is used to replace the placeholder(s) depends on the value of UserAttributeForFilter.\nE.g. \"member={}\" or \"&(objectClass=groupOfNames)(member={})\".\nFor more information about ActiveDirectory filters, see https://ldap.com/ldap-filters.\nNote that the dn (distinguished name) is not an attribute of an entry, so \"dn={}\" cannot be used.\nOptional. When not specified, the default will act as if the filter were specified as\n\"(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})\".\nThis searches nested groups by default.\nNote that nested group search can be slow for some Active Directory servers. To disable it,\nyou can set the filter to\n\"(&(objectClass=group)(member={})\"",
              "type": "string"
            },
            "skipGroupRefresh": {
              "description": "The user's group membership is refreshed as they interact with the supervisor\nto obtain new credentials (as their old credentials expire).  This allows group\nmembership changes to be quickly reflected into Kubernetes clusters.  Since\ngroup membership is often used to bind authorization policies, it is important\nto keep the groups observed in Kubernetes clusters in-sync with the identity\nprovider.\n\n\nIn some environments, frequent group membership queries may result in a\nsignificant performance impact on the identity provider and/or the supervisor.\nThe best approach to handle performance impacts is to tweak the group query\nto be more performant, for example by disabling nested group search or by\nusing a more targeted group search base.\n\n\nIf the group search query cannot be made performant and you are willing to\nhave group memberships remain static for approximately a day, then set\nskipGroupRefresh to true.  This is an insecure configuration as authorization\npolicies that are bound to group membership will not notice if a user has\nbeen removed from a particular group until their next login.\n\n\nThis is an experimental feature that may be removed or significantly altered\nin the future.  Consumers of this configuration should carefully read all\nrelease notes before upgrading to ensure that the meaning of this field has\nnot changed.",
              "type": "boolean"
            },
            "userAttributeForFilter": {
              "description": "UserAttributeForFilter specifies which attribute's value from the user entry found as a result of\nthe user search will be used to replace the \"{}\" placeholder(s) in the group search Filter.\nFor example, specifying \"uid\" as the UserAttributeForFilter while specifying\n\"&(objectClass=posixGroup)(memberUid={})\" as the Filter would search for groups by replacing\nthe \"{}\" placeholder in the Filter with the value of the user's \"uid\" attribute.\nOptional. When not specified, the default will act as if \"dn\" were specified. For example, leaving\nUserAttributeForFilter unspecified while specifying \"&(objectClass=groupOfNames)(member={})\" as the Filter\nwould search for groups by replacing the \"{}\" placeholder(s) with the dn (distinguished name) of the user.",
              "type": "string"
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "host": {
          "description": "Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636.",
          "minLength": 1,
          "type": "string"
        },
        "tls": {
          "description": "TLS contains the connection settings for how to establish the connection to the Host.",
          "properties": {
            "certificateAuthorityData": {
              "description": "X.509 Certificate Authority (base64-encoded PEM bundle). If omitted, a default set of system roots will be trusted.",
              "type": "string"
            },
            "certificateAuthorityDataSource": {
              "description": "Reference to a CA bundle in a secret or a configmap.\nAny changes to the CA bundle in the secret or configmap will be dynamically reloaded.",
              "properties": {
                "key": {
                  "description": "Key is the key name within the secret or configmap from which to read the CA bundle.\nThe value found at this key in the secret or configmap must not be empty, and must be a valid PEM-encoded\ncertificate bundle.",
                  "minLength": 1,
                  "type": "string"
                },
                "kind": {
                  "description": "Kind configures whether the CA bundle is being sourced from a Kubernetes secret or a configmap.\nAllowed values are \"Secret\" or \"ConfigMap\".\n\"ConfigMap\" uses a Kubernetes configmap to source CA Bundles.\n\"Secret\" uses Kubernetes secrets of type kubernetes.io/tls or Opaque to source CA Bundles.",
                  "enum": [
                    "Secret",
                    "ConfigMap"
                  ],
                  "type": "string"
                },
                "name": {
                  "description": "Name is the resource name of the secret or configmap from which to read the CA bundle.\nThe referenced secret or configmap must be created in the same namespace where Pinniped Supervisor is installed.",
                  "minLength": 1,
                  "type": "string"
                }
              },
              "required": [
                "key",
                "kind",
                "name"
              ],
              "type": "object",
              "additionalProperties": false
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "userSearch": {
          "description": "UserSearch contains the configuration for searching for a user by name in Active Directory.",
          "properties": {
            "attributes": {
              "description": "Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as\nthe result of the user search.",
              "properties": {
                "uid": {
                  "description": "UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely\nidentify the user within this ActiveDirectory provider after a successful authentication.\nOptional, when empty this defaults to \"objectGUID\".",
                  "type": "string"
                },
                "username": {
                  "description": "Username specifies the name of the attribute in Active Directory entry whose value shall become the username\nof the user after a successful authentication.\nOptional, when empty this defaults to \"userPrincipalName\".",
                  "type": "string"
                }
              },
              "type": "object",
              "additionalProperties": false
            },
            "base": {
              "description": "Base is the dn (distinguished name) that should be used as the search base when searching for users.\nE.g. \"ou=users,dc=example,dc=com\".\nOptional, when not specified it will be based on the result of a query for the defaultNamingContext\n(see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).\nThe default behavior searches your entire domain for users.\nIt may make sense to specify a subtree as a search base if you wish to exclude some users\nor to make searches faster.",
              "type": "string"
            },
            "filter": {
              "description": "Filter is the search filter which should be applied when searching for users. The pattern \"{}\" must occur\nin the filter at least once and will be dynamically replaced by the username for which the search is being run.\nE.g. \"mail={}\" or \"&(objectClass=person)(uid={})\". For more information about LDAP filters, see\nhttps://ldap.com/ldap-filters.\nNote that the dn (distinguished name) is not an attribute of an entry, so \"dn={}\" cannot be used.\nOptional. When not specified, the default will be\n'(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}\")(mail={})(userPrincipalName={})(sAMAccountType=805306368))'\nThis means that the user is a person, is not a computer, the sAMAccountType is for a normal user account,\nand is not shown in advanced view only\n(which would likely mean its a system created service account with advanced permissions).\nAlso, either the sAMAccountName, the userPrincipalName, or the mail attribute matches the input username.",
              "type": "string"
            }
          },
          "type": "object",
          "additionalProperties": false
        }
      },
      "required": [
        "host"
      ],
      "type": "object",
      "additionalProperties": false
    },
    "status": {
      "description": "Status of the identity provider.",
      "properties": {
        "conditions": {
          "description": "Represents the observations of an identity provider's current state.",
          "items": {
            "description": "Condition contains details for one aspect of the current state of this API Resource.\n---\nThis struct is intended for direct use as an array at the field path .status.conditions.  For example,\n\n\n\ttype FooStatus struct{\n\t    // Represents the observations of a foo's current state.\n\t    // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\"\n\t    // +patchMergeKey=type\n\t    // +patchStrategy=merge\n\t    // +listType=map\n\t    // +listMapKey=type\n\t    Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t    // other fields\n\t}",
            "properties": {
              "lastTransitionTime": {
                "description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.",
                "format": "date-time",
                "type": "string"
              },
              "message": {
                "description": "message is a human readable message indicating details about the transition.\nThis may be an empty string.",
                "maxLength": 32768,
                "type": "string"
              },
              "observedGeneration": {
                "description": "observedGeneration represents the .metadata.generation that the condition was set based upon.\nFor instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\nwith respect to the current state of the instance.",
                "format": "int64",
                "minimum": 0,
                "type": "integer"
              },
              "reason": {
                "description": "reason contains a programmatic identifier indicating the reason for the condition's last transition.\nProducers of specific condition types may define expected values and meanings for this field,\nand whether the values are considered a guaranteed API.\nThe value should be a CamelCase string.\nThis field may not be empty.",
                "maxLength": 1024,
                "minLength": 1,
                "pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
                "type": "string"
              },
              "status": {
                "description": "status of the condition, one of True, False, Unknown.",
                "enum": [
                  "True",
                  "False",
                  "Unknown"
                ],
                "type": "string"
              },
              "type": {
                "description": "type of condition in CamelCase or in foo.example.com/CamelCase.\n---\nMany .condition.type values are consistent across resources like Available, but because arbitrary conditions can be\nuseful (see .node.status.conditions), the ability to deconflict is important.\nThe regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)",
                "maxLength": 316,
                "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
                "type": "string"
              }
            },
            "required": [
              "lastTransitionTime",
              "message",
              "reason",
              "status",
              "type"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "type": "array",
          "x-kubernetes-list-map-keys": [
            "type"
          ],
          "x-kubernetes-list-type": "map"
        },
        "phase": {
          "default": "Pending",
          "description": "Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.",
          "enum": [
            "Pending",
            "Ready",
            "Error"
          ],
          "type": "string"
        }
      },
      "type": "object",
      "additionalProperties": false
    }
  },
  "required": [
    "spec"
  ],
  "type": "object"
}
