Skip to content

Commit

Permalink
Enable remote gRPC and HTTP API
Browse files Browse the repository at this point in the history
This commit enables the existing gRPC and HTTP API from remote locations
as long as the user can provide a valid API key. This allows users to
control their headscale with the CLI from a workstation. 🎉
  • Loading branch information
kradalby committed Jan 25, 2022
1 parent a6e2238 commit 00c69ce
Showing 1 changed file with 41 additions and 29 deletions.
70 changes: 41 additions & 29 deletions app.go
Expand Up @@ -339,26 +339,26 @@ func (h *Headscale) grpcAuthenticationInterceptor(ctx context.Context,
)
}

// TODO(kradalby): Implement API key backend:
// - Table in the DB
// - Key name
// - Encrypted
// - Expiry
//
// Currently all other than localhost traffic is unauthorized, this is intentional to allow
// us to make use of gRPC for our CLI, but not having to implement any of the remote capabilities
// and API key auth
return ctx, status.Error(
codes.Unauthenticated,
"Authentication is not implemented yet",
)
valid, err := h.ValidateAPIKey(strings.TrimPrefix(token, AuthPrefix))
if err != nil {
log.Error().
Caller().
Err(err).
Str("client_address", client.Addr.String()).
Msg("failed to validate token")

// if strings.TrimPrefix(token, AUTH_PREFIX) != a.Token {
// log.Error().Caller().Str("client_address", p.Addr.String()).Msg("invalid token")
// return ctx, status.Error(codes.Unauthenticated, "invalid token")
// }
return ctx, status.Error(codes.Internal, "failed to validate token")
}

// return handler(ctx, req)
if !valid {
log.Info().
Str("client_address", client.Addr.String()).
Msg("invalid token")

return ctx, status.Error(codes.Unauthenticated, "invalid token")
}

return handler(ctx, req)
}

func (h *Headscale) httpAuthenticationMiddleware(ctx *gin.Context) {
Expand All @@ -381,19 +381,30 @@ func (h *Headscale) httpAuthenticationMiddleware(ctx *gin.Context) {

ctx.AbortWithStatus(http.StatusUnauthorized)

// TODO(kradalby): Implement API key backend
// Currently all traffic is unauthorized, this is intentional to allow
// us to make use of gRPC for our CLI, but not having to implement any of the remote capabilities
// and API key auth
//
// if strings.TrimPrefix(authHeader, AUTH_PREFIX) != a.Token {
// log.Error().Caller().Str("client_address", c.ClientIP()).Msg("invalid token")
// c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error", "unauthorized"})
valid, err := h.ValidateAPIKey(strings.TrimPrefix(authHeader, AuthPrefix))
if err != nil {
log.Error().
Caller().
Err(err).
Str("client_address", ctx.ClientIP()).
Msg("failed to validate token")

ctx.AbortWithStatus(http.StatusInternalServerError)

// return
// }
return
}

if !valid {
log.Info().
Str("client_address", ctx.ClientIP()).
Msg("invalid token")

ctx.AbortWithStatus(http.StatusUnauthorized)

return
}

// c.Next()
ctx.Next()
}

// ensureUnixSocketIsAbsent will check if the given path for headscales unix socket is clear
Expand Down Expand Up @@ -630,6 +641,7 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
// service, which can be configured to run on any other port.
go func() {
log.Fatal().
Caller().
Err(http.ListenAndServe(h.cfg.TLSLetsEncryptListen, certManager.HTTPHandler(http.HandlerFunc(h.redirect)))).
Msg("failed to set up a HTTP server")
}()
Expand Down

0 comments on commit 00c69ce

Please sign in to comment.