Hi, Thanks for your sharing and proposal.
I noticed that there mentioned the ApisixConsumer, Consumer in APISIX is more like a global level consumer, when we create one in APISIX, we only need to enable the same Auth Plugin in Routes then they will bind together. Just to make sure, does Ingress Controller have the same action like APISIX does? Could we need to support scoped Consumer? Best Regards! @ Zhiyuan Ju <https://github.com/juzhiyuan> Chao Zhang <tok...@apache.org> 于2021年4月13日周二 下午1:51写道: > Hi, there > > I'm devoting myself to implementing the authentication capability in > APISIX Ingress Controller, and below is my proposal. > > Background > > Authentication and Authorization are required on the Kubernetes > Ingress layer, which is similar to API Gateway. However, due to the > lack of some APISIX Consumer alike stuff, APISIX Ingress Controller > cannot leverage any Authentication plugins provided by APISIX. > > That’s why an appropriate way needs to be developed to make up for > this drawback. > > Research > > The standard Ingress isn’t involve anything about Authentication, thus > every Ingress Controllers implement it in different ways. > > Kong > > As an API Gateway solution, Kong Ingress Controller implements the > KongConsumer CRD, which maps it to the Consumer object in Kong. > > apiVersion: configuration.konghq.com/v1 > kind: KongConsumer > metadata: > name: <object name> > namespace: <object namespace> > annotations: > kubernetes.io/ingress.class: <controller ingress class, "kong" by > default> > username: <user name> > custom_id: <custom ID> > > All KongConsumer resources will be watched by Kong Ingress Controller > and used when authenticating. > > Ingress Nginx > > The Authentication is weak in Ingress Nginx,only basic-auth and digest > authentication are supported. It is implemented by specifying > annotations in Ingress. > > nginx.ingress.kubernetes.io/auth-type: [basic|digest] > > This annotation specifies the authentication type. > > nginx.ingress.kubernetes.io/auth-secret: secretName > > And this annotation specifies the Kubernetes Secret name which stores > the username and password. > > apiVersion: v1 > data: > auth: Zm9vOiRhcHIxJE9GRzNYeWJwJGNrTDBGSERBa29YWUlsSDkuY3lzVDAK > kind: Secret > metadata: > name: basic-auth > namespace: default > type: Opaque > --- > apiVersion: networking.k8s.io/v1beta1 > kind: Ingress > metadata: > name: ingress-with-auth > annotations: > nginx.ingress.kubernetes.io/auth-type: basic > nginx.ingress.kubernetes.io/auth-secret: basic-auth > spec: > rules: > - host: foo.bar.com > http: > paths: > - path: / > backend: > serviceName: http-svc > servicePort: 80 > > How Consumers Work in APISIX > > Consumers are always used with Authentication, you need to configure a > consumer (with username) and enable several plugins on it, then also > enabling these (auth) plugins in the Route. APISIX searches the > consumer according to the auth-type and its key (headers or query > strings). > > Frankly, it also works if we just copy this way to APISIX Ingress > Controller, but the configure is not so clean and easy. As we first > need some kinds of stuff to create the Consumer, then enable (APISIX) > plugins on it, and enabling these plugins on ApisixRoute again. We > need an easier way. > > ApisixConsumer > > ApisixConsumer is necessary as we have to create the consumer. > > apiVersion: apisix.apache.org/v2alpha1 > kind: ApisixConsumer > metadata: > name: <consumer-name> > namespace: <consumer-namespace> > labels: > group: 111 > spec: > authParameter: > basicAuth: > valueRef: # exclusive with value > kind: secret > name: <secret-name> > namespace: <secret-namespace> > value: # exclusive with valueRef > username: aaa > password: xxx > keyAuth: > key: xxxx # exclusive with keyRef > keyRef: # exclusive with key > kind: secret > name: <secret-name> > namespace: <secret-namespace> > > Currently, only fields under authParameter are concerned (other > features like limit-rate, can be put under rateLimiting field and so > on), which represents authentications, more auth types can be > implemented there, values are kind-dependent, for instance, basic auth > needs a username and password configuration in value or importing from > a secret (exclusively), in valueRef. > > All ApisixConsumers will be watched by APISIX Ingress Controller, and > corresponding Consumer objects will be created, which name is > concatenated by the namespace and name (so it can be unique). > > All authentication configurations will be translated to the > corresponding underlying plugins. > > You may wonder that why not just using the native plugin way here. > This is because the fields above (e.g. password in basic auth) are > sensitive and just configuring literally is not so safe, a better way > is fetching them from Kubernetes secret, also, the native plugin > configuring is too flexible to manage, it might results in some > security issues (since validation is not so strong so far). > > ApisixRoute > > On the other hand, authentication should be enabled in ApisixRoute, of > course, it can be supported by configuring the plugins field: > > apiVersion: apisix.apache.org/v2alpha1 > kind: ApisixRoute > metadata: > name: test > spec: > http: > - name: rule1 > match: > paths: > - /* > backend: > serviceName: httpbin > servicePort: 8080 > plugins: > - name: basic-auth > enable: true > > Considering some capabilities like consumer restriction (ACL) and a > unifying way for management, native fields will be better here. > > apiVersion: apisix.apache.org/v2alpha1 > kind: ApisixRoute > metadata: > name: test > spec: > http: > - name: rule1 > match: > paths: > - /* > backend: > serviceName: httpbin > servicePort: 8080 > authentication: > enable: true > type: keyAuth > keyAuth: > header: Authorization > acl: > allowedConsumers: > selector: > group: 111 > deniedConsumers: > selector: > group: 222 > rejectedCode: 503 > > Just enabling the required authentication way in ApisixRoute and > configuring the ACL (consumer restriction) on demand. > > In practice, people won’t configure more than one authentication > method in a Route, so here the authentication type must be configured, > any extra configurations can be put under another field which name is > the same as the authentication type (e.g. configurations for keyAuth > is under keyAuth field). > > As for ACL, Kuberentes typical label-selector is applied as the > consumer list might be huge. In this case, it’s not easy to maintain > such an ApisixRoute object. > > All the authentications and ACL will be translated to the underlying > APISIX plugins. > > Thanks! > Chao Zhang > GitHub: https://github.com/tokers >