Prise en charge de l'agent de stratégie ouverte pour Kubernetes avec NetScaler
L'agent de stratégie ouverte (OPA) est un moteur de stratégie open source et à usage général qui unifie l'application des stratégies sur différentes technologies et systèmes. OPA fournit un langage déclaratif de haut niveau qui vous permet de spécifier la stratégie sous forme de code et des API simples pour décharger la prise de décision en matière de stratégie de votre logiciel. En utilisant OPA, vous pouvez découpler la prise de décision en matière de stratégie de l'application de la stratégie. Vous pouvez utiliser OPA pour appliquer des stratégies via NetScaler dans un environnement Kubernetes.
Avec OPA, vous pouvez créer un système centralisé de prise de décision en matière de stratégie pour un environnement impliquant plusieurs NetScaler ou plusieurs appareils distribués. L'avantage de cette approche est que vous n'avez à apporter des modifications que sur le serveur OPA pour toute modification spécifique à une décision applicable à plusieurs appareils.
Pour plus d'informations sur OPA, consultez la documentation OPA.
L'intégration OPA sur NetScaler peut être prise en charge via un appel HTTP (HTTP callout), où OPA peut être utilisé avec ou sans authentification. Un appel HTTP est une requête HTTP ou HTTPS que l'appliance NetScaler génère et envoie à une application externe dans le cadre de l'évaluation de la stratégie.
Pour plus d'informations sur la prise en charge des appels HTTP, consultez la documentation sur les appels HTTP.
Pour plus d'informations sur la prise en charge de l'authentification, consultez les stratégies d'authentification et d'autorisation pour Kubernetes avec NetScaler.
Le diagramme suivant donne un aperçu de la manière d'intégrer OPA à la solution cloud native NetScaler.
Dans le diagramme d'intégration OPA, chaque numéro représente la tâche correspondante dans la liste suivante :
-
Création des objets Kubernetes requis à l'aide des commandes Kubernetes. Cette étape doit inclure la création du CRD pour envoyer l'appel HTTP au serveur OPA.
-
Configuration de NetScaler. NetScaler est automatiquement configuré par NetScaler Ingress Controller en fonction des objets Kubernetes créés.
-
Envoi de la requête utilisateur pour les ressources depuis le client. L'utilisateur peut être authentifié si des CRD d'authentification sont créés.
-
Envoi d'un appel HTTP au serveur OPA au format JSON depuis NetScaler, transportant les paramètres d'autorisation.
-
Envoi de la décision d'autorisation depuis le serveur OPA basé sur les règles définies dans REGO, le langage de stratégie pour OPA.
-
Envoi de la réponse au client en fonction de la décision d'autorisation.
Exemples de cas d'utilisation
Exemple 1 : Autoriser ou refuser l'accès aux ressources en fonction de l'adresse IP source du client
Voici un exemple de politique d'appel HTTP vers le serveur OPA utilisant la CRD de politique de réécriture pour autoriser ou refuser l'accès aux ressources en fonction de l'adresse IP source du client et des règles OPA correspondantes.
Dans cet exemple, le serveur OPA répond avec
"result": true si l'adresse IP source du client est 192.2.162.0/24, sinon il répond avec "result":false.
apiVersion: citrix.com/v1
kind: rewritepolicy
metadata:
name: calloutexample
spec:
responder-policies:
- servicenames:
- frontend
responder-policy:
respondwith:
http-payload-string: '"HTTP/1.1 401 Access denied\r\n\r\n"' #Access is denied if the respose from OPA server contains false.
respond-criteria: 'sys.http_callout("callout_name").CONTAINS("false")'
comment: 'Invalid access'
httpcallout_policy:
- name: callout_name
server_ip: "192.2.156.160" #OPA Server IP
server_port: 8181 #OPA Server Port
http_method: 'POST'
host_expr: "\"192.2.156.160\""
url_stem_expr: "\"/v1/data/example/allow\"" #URL stem expression to be used
body_expr: '"{\"input\": {\"clientinfo\": [{\"id\": \"ci\", \"ip\": [\""+ CLIENT.IP.SRC +"\"]}]}}"' #JSON to OPA server carrying client IP
headers:
- name: Content-Type
expr: '"application/json"'
return_type: TEXT
result_expr: "HTTP.RES.BODY(100)"
Voici les règles définies via le langage de politique Rego sur le serveur OPA pour la politique d'appel HTTP de cet exemple :
package example
default allow = false # unless otherwise defined, allow is false
allow = true { # allow is true if...
count(violation) != 0 # the ip matches regex.
}
violation[client.id] { # a client is in the violation set if...
client := input.clientinfo[_]
regex.match("192.2.162.", client.ip[_]) # the client is not part of 192.2.162.0/24 network.
}
Exemple 2 : Autoriser ou refuser l'accès en fonction du groupe d'utilisateurs après authentification
Voici un exemple de politique d'appel HTTP vers le serveur OPA utilisant la CRD de politique de réécriture pour autoriser ou refuser l'accès aux ressources en fonction du groupe d'utilisateurs après authentification et des règles OPA correspondantes.
Dans cet exemple, le serveur OPA répond avec
"result":true si l'utilisateur fait partie du groupe beverages, sinon il répond avec "result":false.
Voici la politique d'appel HTTP vers le serveur OPA via la CRD de politique de réécriture.
apiVersion: citrix.com/v1
kind: rewritepolicy
metadata:
name: calloutexample
spec:
responder-policies:
- servicenames:
- frontend
responder-policy:
respondwith:
http-payload-string: '"HTTP/1.1 401 Access denied\r\n\r\n"' #Access is denied if the respose from OPA server contains false.
respond-criteria: 'sys.http_callout("callout_name").CONTAINS("false")'
comment: 'Invalid access'
httpcallout_policy:
- name: callout_name
server_ip: "192.2.156.160" #OPA Server IP
server_port: 8181 #OPA Server Port
http_method: 'POST'
host_expr: "\"192.2.156.160\""
url_stem_expr: "\"/v1/data/example/allow\"" #URL stem expression to be used
body_expr: '"{\"input\": {\"users\": [{\"name\": \""+ AAA.USER.NAME +"\", \"group\": [\""+ AAA.USER.GROUPS +"\"]}]}}"' #JSON to OPA server carrying username and group information
headers:
- name: Content-Type
expr: '"application/json"'
return_type: TEXT
result_expr: "HTTP.RES.BODY(100)"
Voici les règles définies via le langage Rego sur le serveur OPA pour cet exemple :
package example
default allow = false # unless otherwise defined, allow is false
allow = true { # allow is true if...
count(isbeveragesuser) != 0 # the user is part of beverages group.
}
isbeveragesuser[user.name] { # a user is beverages user...
user := input.users[_]
user.group[_] == "beverages" # if it is part of beverages group.
}
Vous pouvez effectuer l'authentification en utilisant l'en-tête de requête (basée sur 401) ou via des formulaires.
Voici un exemple de politique d'authentification utilisant l'authentification basée sur l'en-tête de requête. Dans cette politique, l'authentification locale est utilisée.
apiVersion: citrix.com/v1beta1
kind: authpolicy
metadata:
name: localauth
spec:
servicenames:
- frontend
authentication_mechanism:
using_request_header: 'ON'
authentication_providers:
- name: "local-auth-provider"
basic_local_db:
use_local_auth: 'YES'
authentication_policies:
- resource:
path: []
method: []
provider: ["local-auth-provider"]
authorization_policies:
- resource:
path: []
method: []
claims: []
Voici un exemple de politique d'authentification utilisant l'authentification basée sur les formulaires. Dans cette politique, l'authentification locale est utilisée.
apiVersion: citrix.com/v1beta1
kind: authpolicy
metadata:
name: localauth
spec:
servicenames:
- frontend
authentication_mechanism:
using_forms:
authentication_host: "fqdn_authenticaton_host"
authentication_host_cert:
tls_secret: authhost-tls-cert-secret
vip: "192.2.156.156"
authentication_providers:
- name: "local-auth-provider"
basic_local_db:
use_local_auth: 'YES'
authentication_policies:
- resource:
path: []
method: []
provider: ["local-auth-provider"]
authorization_policies:
- resource:
path: []
method: []
claims: []
Exemple 3 : Autoriser ou refuser l'accès en fonction des attributs d'authentification obtenus lors de l'authentification
Voici un exemple de politique d'appel HTTP vers le serveur OPA utilisant le CRD de politique de réécriture pour autoriser ou refuser l'accès en fonction des attributs d'authentification obtenus lors de l'authentification et des règles OPA correspondantes.
Dans cet exemple, le serveur OPA répond avec
"result":true' si l'attribut memberof de l'utilisateur contient grp1, sinon il répond avec "result":false.
Voici un exemple de politique d'appel HTTP vers le serveur OPA via le CRD de politique de réécriture :
apiVersion: citrix.com/v1
kind: rewritepolicy
metadata:
name: calloutexample
spec:
responder-policies:
- servicenames:
- frontend
responder-policy:
respondwith:
http-payload-string: '"HTTP/1.1 401 Access denied\r\n\r\n"' #Access is denied if the respose from OPA server contains false.
respond-criteria: 'sys.http_callout("callout_name").CONTAINS("false")'
comment: 'Invalid access'
httpcallout_policy:
- name: callout_name
server_ip: "192.2.156.160" #OPA Server IP
server_port: 8181 #OPA Server Port
http_method: 'POST'
host_expr: "\"192.2.156.160\""
url_stem_expr: "\"/v1/data/example/allow\"" #URL stem expression to be used
body_expr: '"{\"input\": {\"users\": [{\"name\": \""+ AAA.USER.NAME +"\", \"attr\": [\""+ aaa.user.attribute("memberof") +"\"]}]}}"' #JSON to OPA server carrying username and "memberof" attribute information
headers:
- name: Content-Type
expr: '"application/json"'
return_type: TEXT
result_expr: "HTTP.RES.BODY(100)"
Voici les règles définies via le langage Rego sur le serveur OPA pour cet exemple :
package example
default allow = false # unless otherwise defined, allow is false
allow = true { # allow is true if...
count(isbeveragesuser) != 0 # the user is part of grp1.
}
isbeveragesuser[user.name] { # a user is part of allow group...
user := input.users[_]
regex.match("CN=grp1", user.attr[_]) # if it is part of grp1 group.
}
Vous pouvez effectuer l'authentification en utilisant l'en-tête de requête (basée sur 401) ou via des formulaires. Dans cet exemple, l'authentification LDAP est utilisée, où l'attribut
memberof de l'utilisateur est obtenu du serveur LDAP pendant l'authentification.
Voici un exemple de politique d'authentification utilisant l'authentification basée sur l'en-tête de requête.
apiVersion: citrix.com/v1beta1
kind: authpolicy
metadata:
name: ldapauth
spec:
servicenames:
- frontend
authentication_mechanism:
using_request_header: 'ON'
authentication_providers:
- name: "ldap-auth-provider"
ldap:
server_ip: "192.2.156.160"
base: 'dc=aaa,dc=local'
login_name: accountname
sub_attribute_name: CN
server_login_credentials: ldapcredential
attributes_to_save: memberof #memberof attribute to be obtained from LDAP server for user
authentication_policies:
- resource:
path: []
method: []
provider: ["ldap-auth-provider"]
authorization_policies:
- resource:
path: []
method: []
claims: []
Voici un exemple de politique d'authentification utilisant l'authentification basée sur les formulaires.
apiVersion: citrix.com/v1beta1
kind: authpolicy
metadata:
name: authhotdrinks
spec:
servicenames:
- frontend
authentication_mechanism:
using_forms:
authentication_host: "fqdn_authenticaton_host"
authentication_host_cert:
tls_secret: authhost-tls-cert-secret
vip: "192.2.156.156"
authentication_providers:
- name: "ldap-auth-provider"
ldap:
server_ip: "192.2.156.160"
base: 'dc=aaa,dc=local'
login_name: accountname
sub_attribute_name: CN
server_login_credentials: ldapcredential
attributes_to_save: memberof #memberof attribute to be obtained from LDAP server for user
authentication_policies:
- resource:
path: []
method: []
provider: ["ldap-auth-provider"]