ExtractProvisionerDaemonAuthenticated authenticates a request as a provisioner daemon. If the request is not authenticated, the next handler is called unless Optional is true. This function currently is tested inside the enterprise package.
(opts ExtractProvisionerAuthConfig)
| 29 | // If the request is not authenticated, the next handler is called unless Optional is true. |
| 30 | // This function currently is tested inside the enterprise package. |
| 31 | func ExtractProvisionerDaemonAuthenticated(opts ExtractProvisionerAuthConfig) func(next http.Handler) http.Handler { |
| 32 | return func(next http.Handler) http.Handler { |
| 33 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 34 | ctx := r.Context() |
| 35 | |
| 36 | handleOptional := func(code int, response codersdk.Response) { |
| 37 | if opts.Optional { |
| 38 | next.ServeHTTP(w, r) |
| 39 | return |
| 40 | } |
| 41 | httpapi.Write(ctx, w, code, response) |
| 42 | } |
| 43 | |
| 44 | psk := r.Header.Get(codersdk.ProvisionerDaemonPSK) |
| 45 | key := r.Header.Get(codersdk.ProvisionerDaemonKey) |
| 46 | if key == "" { |
| 47 | if opts.PSK == "" { |
| 48 | handleOptional(http.StatusUnauthorized, codersdk.Response{ |
| 49 | Message: "provisioner daemon key required", |
| 50 | }) |
| 51 | return |
| 52 | } |
| 53 | |
| 54 | fallbackToPSK(ctx, opts.PSK, next, w, r, handleOptional) |
| 55 | return |
| 56 | } |
| 57 | if psk != "" { |
| 58 | handleOptional(http.StatusBadRequest, codersdk.Response{ |
| 59 | Message: "provisioner daemon key and psk provided, but only one is allowed", |
| 60 | }) |
| 61 | return |
| 62 | } |
| 63 | |
| 64 | err := provisionerkey.Validate(key) |
| 65 | if err != nil { |
| 66 | handleOptional(http.StatusBadRequest, codersdk.Response{ |
| 67 | Message: "provisioner daemon key invalid", |
| 68 | Detail: err.Error(), |
| 69 | }) |
| 70 | return |
| 71 | } |
| 72 | hashedKey := provisionerkey.HashSecret(key) |
| 73 | // nolint:gocritic // System must check if the provisioner key is valid. |
| 74 | pk, err := opts.DB.GetProvisionerKeyByHashedSecret(dbauthz.AsSystemRestricted(ctx), hashedKey) |
| 75 | if err != nil { |
| 76 | if httpapi.Is404Error(err) { |
| 77 | handleOptional(http.StatusUnauthorized, codersdk.Response{ |
| 78 | Message: "provisioner daemon key invalid", |
| 79 | }) |
| 80 | return |
| 81 | } |
| 82 | |
| 83 | handleOptional(http.StatusInternalServerError, codersdk.Response{ |
| 84 | Message: "get provisioner daemon key", |
| 85 | Detail: err.Error(), |
| 86 | }) |
| 87 | return |
| 88 | } |