Caddy: help: authentication plugin development

Created on 16 Apr 2020  Â·  15Comments  Â·  Source: caddyserver/caddy

Hi @mholt , I am porting a SAML authentication plugin from v1 to v2.

The core of the plugin code is here.

I did the following:

When I ran a test, I get the following error:

{"level":"error","ts":1586932887.094906,"logger":"admin.api","msg":"request error","error":"loading config: loading new config: loading samlauth app module: unknown module: samlauth","status_code":400}

In the "Extending Caddy Tutorial", there was a phrase "Apps are modules with an empty namespace". This particular module is registered in the following way:

// CaddyModule returns the Caddy module information.
func (SamlAuth) CaddyModule() caddy.ModuleInfo {
    return caddy.ModuleInfo{
        ID:  "http.authentication.providers.samlauth",
        New: func() caddy.Module { return new(SamlAuth) },
    }
}

That is, it is in "http.authentication.providers" namespace.

Whay is the module not being recognized? Perhaps, it is not in the correct configuration section? Should it not be in "http.authentication.providers"? Do authentication modules follow the same pattern as "apps"?

question

Most helpful comment

@mholt , @nchagrass-bud , thank you for your help! I think I am on a different issue (related to logging) now :-)

side :speech_balloon: @mholt, the idea of xcaddy is awesome!

The configuration that worked was:

    TestPlugin: caddytest.go:93: ----------- failed with config -----------
        {
          "apps": {
            "http": {
              "http_port": 9080,
              "https_port": 9443,
              "servers": {
                "srv0": {
                  "listen": [
                    ":9443"
                  ],
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "authentication",
                          "providers": {
                            "samlauth": {
                              "auth_url": "/saml",
                              "azure": {
                                "acs_urls": [
                                  "https://localhost:9443/login"
                                ],
                                "application_id": "623cae7c-e6b2-43c5-853c-2059c9b2cb58",
                                "application_name": "My Infosec",
                                "entity_id": "https://localhost:9443/login",
                                "idp_metadata_location": "/etc/saml/azure_ad_idp_metadata.xml",
                                "idp_sign_cert_location": "/etc/saml/azure_ad_signing_cert.pem",
                                "tenant_id": "1b9e886b-8ff2-4378-b6c8-6771259a5f51"
                              },
                              "jwt_token_name": "JWT_TOKEN",
                              "jwt_token_secret": "383aca9a-1c39-4d7a-b4d8-67ba4718dd3f"
                            }
                          }
                        },
                        {
                          "handler": "subroute",
                          "routes": [
                            {
                              "handle": [
                                {
                                  "body": "1.0.0",
                                  "handler": "static_response",
                                  "status_code": 200
                                }
                              ],
                              "match": [
                                {
                                  "path": [
                                    "/version"
                                  ]
                                }
                              ]
                            }
                          ]
                        }
                      ],
                      "match": [
                        {
                          "host": [
                            "127.0.0.1"
                          ]
                        }
                      ],
                      "terminal": true
                    }
                  ],
                  "tls_connection_policies": [
                    {
                      "certificate_selection": {
                        "any_tag": [
                          "cert0"
                        ]
                      },
                      "match": {
                        "sni": [
                          "127.0.0.1"
                        ]
                      }
                    },
                    {
                      "default_sni": "*.caddy.localhost"
                    }
                  ]
                }
              }
            },
            "pki": {
              "certificate_authorities": {
                "local": {
                  "install_trust": false
                }
              }
            },
            "tls": {
              "certificates": {
                "load_files": [
                  {
                    "certificate": "/home/greenpau/dev/go/pkg/mod/github.com/caddyserver/caddy/[email protected]/caddytest/caddy.localhost.crt",
                    "key": "/home/greenpau/dev/go/pkg/mod/github.com/caddyserver/caddy/[email protected]/caddytest/caddy.localhost.key",
                    "tags": [
                      "cert0"
                    ]
                  }
                ]
              }
            }
          }
        }
--- FAIL: TestPlugin (0.02s)

All 15 comments

Hi!
I feel like I can answer that one, you have to play with the global options expressed here https://caddyserver.com/docs/caddyfile/options and use:
order <dir1> first|last|[before|after <dir2>]

such as

  order samlauth before request_header

Hope that help ; )

Ooo, it would be good to bring @roblabla into this conversation.

@nchagrass-bud That is in fact the way to develop new Caddyfile directives! But I'm not sure if he's using the Caddyfile here or what.

@greenpau How are you running Caddy? What is your config? Are you using xcaddy?

@nchagrass-bud , thank you for stepping in! :+1:

@greenpau How are you running Caddy? What is your config? Are you using xcaddy?

@mholt , I run caddytest server in my unit test as a way to mock caddy. Is it a good approach? xcaddy would be an integration test.

Please see https://github.com/greenpau/samlauth/blob/8925136d367914260e1c67bf14e0d51a1d49d814/samlauth_test.go

Ooo, it would be good to bring @roblabla into this conversation.

@mholt , it is basically almost the same discussion as in "caddy-jwt" :smile:

I feel like I can answer that one, you have to play with the global options expressed here https://caddyserver.com/docs/caddyfile/options and use:

@nchagrass-bud , it looks like "samlauth" indeed belongs to global options :-) What is the way to register it as a global option?

@greenpau

it is basically almost the same discussion as in "caddy-jwt"

I just want to make sure all the developers of authentication plugins are communicating with each other in case we need to make changes to the API, at least early on -- an API which I'm still documenting as experimental for now. (Although I hope no changes are needed.)

I run caddytest server in my unit test as a way to mock caddy. Is it a good approach? xcaddy would be an integration test.

I think that's the other way around :smile: xcaddy should be used to plug in and run Caddy with your module; caddytest should be used for integration tests.

Run xcaddy just like caddy.

Please see https://github.com/greenpau/samlauth/blob/8925136d367914260e1c67bf14e0d51a1d49d814/samlauth_test.go

Ah, it's in the wrong place. Notice where the basic_auth module is in the JSON: https://caddyserver.com/docs/json/apps/http/servers/routes/handle/authentication/providers/http_basic/ (check breadcrumb):

JSON Config Structure › apps › http › servers › routes › handle › authentication › providers › http_basic

Ah, it's in the wrong place.

@mholt , let me try it out! :+1:

@mholt , @nchagrass-bud , thank you for your help! I think I am on a different issue (related to logging) now :-)

side :speech_balloon: @mholt, the idea of xcaddy is awesome!

The configuration that worked was:

    TestPlugin: caddytest.go:93: ----------- failed with config -----------
        {
          "apps": {
            "http": {
              "http_port": 9080,
              "https_port": 9443,
              "servers": {
                "srv0": {
                  "listen": [
                    ":9443"
                  ],
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "authentication",
                          "providers": {
                            "samlauth": {
                              "auth_url": "/saml",
                              "azure": {
                                "acs_urls": [
                                  "https://localhost:9443/login"
                                ],
                                "application_id": "623cae7c-e6b2-43c5-853c-2059c9b2cb58",
                                "application_name": "My Infosec",
                                "entity_id": "https://localhost:9443/login",
                                "idp_metadata_location": "/etc/saml/azure_ad_idp_metadata.xml",
                                "idp_sign_cert_location": "/etc/saml/azure_ad_signing_cert.pem",
                                "tenant_id": "1b9e886b-8ff2-4378-b6c8-6771259a5f51"
                              },
                              "jwt_token_name": "JWT_TOKEN",
                              "jwt_token_secret": "383aca9a-1c39-4d7a-b4d8-67ba4718dd3f"
                            }
                          }
                        },
                        {
                          "handler": "subroute",
                          "routes": [
                            {
                              "handle": [
                                {
                                  "body": "1.0.0",
                                  "handler": "static_response",
                                  "status_code": 200
                                }
                              ],
                              "match": [
                                {
                                  "path": [
                                    "/version"
                                  ]
                                }
                              ]
                            }
                          ]
                        }
                      ],
                      "match": [
                        {
                          "host": [
                            "127.0.0.1"
                          ]
                        }
                      ],
                      "terminal": true
                    }
                  ],
                  "tls_connection_policies": [
                    {
                      "certificate_selection": {
                        "any_tag": [
                          "cert0"
                        ]
                      },
                      "match": {
                        "sni": [
                          "127.0.0.1"
                        ]
                      }
                    },
                    {
                      "default_sni": "*.caddy.localhost"
                    }
                  ]
                }
              }
            },
            "pki": {
              "certificate_authorities": {
                "local": {
                  "install_trust": false
                }
              }
            },
            "tls": {
              "certificates": {
                "load_files": [
                  {
                    "certificate": "/home/greenpau/dev/go/pkg/mod/github.com/caddyserver/caddy/[email protected]/caddytest/caddy.localhost.crt",
                    "key": "/home/greenpau/dev/go/pkg/mod/github.com/caddyserver/caddy/[email protected]/caddytest/caddy.localhost.key",
                    "tags": [
                      "cert0"
                    ]
                  }
                ]
              }
            }
          }
        }
--- FAIL: TestPlugin (0.02s)

Great!!

Your plugins is looking good!

(Maybe rename it to just saml? Any reason to add auth to the name?)

Will close this then, feel free to reopen if necessary like if there's an issue in Caddy itself. We can also help with programming questions on the forum.

(Maybe rename it to just saml? Any reason to add auth to the name?)

@mholt , the thinking is that maybe someone else would have saml plugin, which would be much better than the one I created :-)

@mholt , will rename it to saml.

@mholt , have you thought about plugin naming convention for repositories? e.g. caddy-auth-saml? I was thinking of changing the name from samlauth to caddy-auth-saml.

the thinking is that maybe someone else would have saml plugin, which would be much better than the one I created :-)

ideally that someone else should contribute to improve yours! 😀

caddy-auth-saml sounds good to me.

ideally that someone else should contribute to improve yours! grinning

@francislavoie , agreed :-)

caddy-auth-saml sounds good to me.

@francislavoie, :+1:

@nchagrass-bud @mholt @francislavoie moved the plugin to https://github.com/greenpau/caddy-auth-saml

Was this page helpful?
0 / 5 - 0 ratings

Related issues

la0wei picture la0wei  Â·  3Comments

treviser picture treviser  Â·  3Comments

klaasel picture klaasel  Â·  3Comments

ericmdantas picture ericmdantas  Â·  3Comments

jgsqware picture jgsqware  Â·  3Comments