Skip to content

Commit

Permalink
Upgrade microcluster to LTS version
Browse files Browse the repository at this point in the history
Signed-off-by: Guillaume Boutry <[email protected]>
  • Loading branch information
gboutry committed Sep 23, 2024
1 parent 345b17e commit 4446142
Show file tree
Hide file tree
Showing 34 changed files with 337 additions and 305 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-snap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
uses: actions/checkout@v3

- name: Build snap locally
uses: snapcore/action-build@v1
uses: canonical/action-build@v1.3.0
id: snapcraft

- name: Upload locally built snap artifact
Expand Down
41 changes: 20 additions & 21 deletions sunbeam-microcluster/access/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"github.com/canonical/lxd/lxd/response"
"github.com/canonical/lxd/shared/logger"

"github.com/canonical/microcluster/rest"
"github.com/canonical/microcluster/rest/access"
"github.com/canonical/microcluster/state"
"github.com/canonical/microcluster/v2/rest"
"github.com/canonical/microcluster/v2/rest/access"
"github.com/canonical/microcluster/v2/state"

"github.com/canonical/snap-openstack/sunbeam-microcluster/client"
)
Expand All @@ -20,49 +20,48 @@ import (
// It checks if the request is trusted and verifies the client certificate against the cluster CA.
// If the request is trusted or the client certificate is successfully verified, it allows the request.
// Otherwise, it returns a forbidden response.
func AuthenticateClusterCAHandler(state *state.State, r *http.Request) response.Response {
func AuthenticateClusterCAHandler(state state.State, r *http.Request) (bool, response.Response) {

resp := access.AllowAuthenticated(state, r)
trusted, resp := access.AllowAuthenticated(state, r)

// AllowAuthenticated returns EmptySyncResponse if the request is trusted.
if resp == response.EmptySyncResponse {
return resp
if trusted {
return trusted, resp
}

leader, err := state.Leader()

if err != nil {
logger.Errorf("Failed to get leader client: %v", err)
return response.InternalError(err)
return false, response.InternalError(err)
}

// If this takes too long, we should look into caching the cluster CA.
clusterCA, err := client.ConfigClusterCAGet(state.Context, leader)
clusterCA, err := client.ConfigClusterCAGet(r.Context(), leader)
if err != nil {
// If no CA is configured, simply reject the request
if strings.Contains(err.Error(), "not found") {
logger.Debug("No cluster CA configured, rejecting request")
return response.Forbidden(nil)
return false, response.Forbidden(nil)
}
logger.Errorf("Failed to get cluster CA: %v", err)
return response.InternalError(nil)
return false, response.InternalError(nil)
}

roots := x509.NewCertPool()
ok := roots.AppendCertsFromPEM([]byte(clusterCA))
if !ok {
logger.Error("Failed to parse cluster CA")
return response.InternalError(nil)
return false, response.InternalError(nil)
}

if r.TLS == nil {
logger.Error("Rejecting request without TLS")
return response.Forbidden(nil)
return false, response.Forbidden(nil)
}

if len(r.TLS.PeerCertificates) > 10 {
logger.Error("Rejecting request with too many certificates")
return response.Forbidden(nil)
return false, response.Forbidden(nil)
}

opts := x509.VerifyOptions{
Expand All @@ -75,23 +74,23 @@ func AuthenticateClusterCAHandler(state *state.State, r *http.Request) response.
_, err := cert.Verify(opts)
if err == nil {
logger.Debug("Allowing request authenticated using cluster CA")
return response.EmptySyncResponse
return true, nil
}
}

return response.Forbidden(nil)
return false, response.Forbidden(nil)
}

// AuthenticateUnixHandler only allow requests coming from the unix socket.
func AuthenticateUnixHandler(_ *state.State, r *http.Request) response.Response {
func AuthenticateUnixHandler(_ state.State, r *http.Request) (bool, response.Response) {
if r.RemoteAddr == "@" {
return response.EmptySyncResponse
return true, nil
}
return response.Forbidden(nil)
return false, response.Forbidden(nil)
}

// ClusterCATrustedEndpoint is a helper to simplify the creation of a cluster peer endpoint.
func ClusterCATrustedEndpoint(handler func(state *state.State, r *http.Request) response.Response, proxyTarget bool) rest.EndpointAction {
func ClusterCATrustedEndpoint(handler func(state state.State, r *http.Request) response.Response, proxyTarget bool) rest.EndpointAction {
return rest.EndpointAction{
Handler: handler,
AccessHandler: AuthenticateClusterCAHandler,
Expand Down
6 changes: 3 additions & 3 deletions sunbeam-microcluster/api/certificates.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (

"github.com/canonical/lxd/lxd/response"
"github.com/canonical/lxd/shared/logger"
"github.com/canonical/microcluster/rest"
"github.com/canonical/microcluster/state"
"github.com/canonical/microcluster/v2/rest"
"github.com/canonical/microcluster/v2/state"
"github.com/canonical/snap-openstack/sunbeam-microcluster/access"
"github.com/canonical/snap-openstack/sunbeam-microcluster/api/types"
)
Expand All @@ -22,7 +22,7 @@ var certPair = rest.Endpoint{
}

// Return the member server certpair, should only be allowed over the Unix socket.
func cmdGetMemberServerCertPair(s *state.State, _ *http.Request) response.Response {
func cmdGetMemberServerCertPair(s state.State, _ *http.Request) response.Response {
certs := s.ServerCert()

if certs == nil {
Expand Down
16 changes: 8 additions & 8 deletions sunbeam-microcluster/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (

"github.com/canonical/lxd/lxd/response"
"github.com/canonical/lxd/shared/api"
"github.com/canonical/microcluster/rest"
"github.com/canonical/microcluster/state"
"github.com/canonical/microcluster/v2/rest"
"github.com/canonical/microcluster/v2/state"
"github.com/gorilla/mux"

"github.com/canonical/snap-openstack/sunbeam-microcluster/access"
Expand All @@ -24,13 +24,13 @@ var configCmd = rest.Endpoint{
Delete: access.ClusterCATrustedEndpoint(cmdConfigDelete, true),
}

func cmdConfigGet(s *state.State, r *http.Request) response.Response {
func cmdConfigGet(s state.State, r *http.Request) response.Response {
var key string
key, err := url.PathUnescape(mux.Vars(r)["key"])
if err != nil {
return response.InternalError(err)
}
config, err := sunbeam.GetConfig(s, key)
config, err := sunbeam.GetConfig(r.Context(), s, key)
if err != nil {
if err, ok := err.(api.StatusError); ok {
if err.Status() == http.StatusNotFound {
Expand All @@ -43,7 +43,7 @@ func cmdConfigGet(s *state.State, r *http.Request) response.Response {
return response.SyncResponse(true, config)
}

func cmdConfigPut(s *state.State, r *http.Request) response.Response {
func cmdConfigPut(s state.State, r *http.Request) response.Response {
key, err := url.PathUnescape(mux.Vars(r)["key"])
if err != nil {
return response.InternalError(err)
Expand All @@ -55,21 +55,21 @@ func cmdConfigPut(s *state.State, r *http.Request) response.Response {
return response.InternalError(err)
}

err = sunbeam.UpdateConfig(s, key, body.String())
err = sunbeam.UpdateConfig(r.Context(), s, key, body.String())
if err != nil {
return response.InternalError(err)
}

return response.EmptySyncResponse
}

func cmdConfigDelete(s *state.State, r *http.Request) response.Response {
func cmdConfigDelete(s state.State, r *http.Request) response.Response {
key, err := url.PathUnescape(mux.Vars(r)["key"])
if err != nil {
return response.InternalError(err)
}

err = sunbeam.DeleteConfig(s, key)
err = sunbeam.DeleteConfig(r.Context(), s, key)
if err != nil {
if err, ok := err.(api.StatusError); ok {
if err.Status() == http.StatusNotFound {
Expand Down
20 changes: 10 additions & 10 deletions sunbeam-microcluster/api/jujuuser.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (

"github.com/canonical/lxd/lxd/response"
"github.com/canonical/lxd/shared/api"
"github.com/canonical/microcluster/rest"
"github.com/canonical/microcluster/state"
"github.com/canonical/microcluster/v2/rest"
"github.com/canonical/microcluster/v2/state"
"github.com/gorilla/mux"

"github.com/canonical/snap-openstack/sunbeam-microcluster/access"
Expand All @@ -32,22 +32,22 @@ var jujuuserCmd = rest.Endpoint{
Delete: access.ClusterCATrustedEndpoint(cmdJujuUsersDelete, true),
}

func cmdJujuUsersGetAll(s *state.State, _ *http.Request) response.Response {
users, err := sunbeam.ListJujuUsers(s)
func cmdJujuUsersGetAll(s state.State, r *http.Request) response.Response {
users, err := sunbeam.ListJujuUsers(r.Context(), s)
if err != nil {
return response.InternalError(err)
}

return response.SyncResponse(true, users)
}

func cmdJujuUsersGet(s *state.State, r *http.Request) response.Response {
func cmdJujuUsersGet(s state.State, r *http.Request) response.Response {
var name string
name, err := url.PathUnescape(mux.Vars(r)["name"])
if err != nil {
return response.InternalError(err)
}
jujuUser, err := sunbeam.GetJujuUser(s, name)
jujuUser, err := sunbeam.GetJujuUser(r.Context(), s, name)
if err != nil {
if err, ok := err.(api.StatusError); ok {
if err.Status() == http.StatusNotFound {
Expand All @@ -60,28 +60,28 @@ func cmdJujuUsersGet(s *state.State, r *http.Request) response.Response {
return response.SyncResponse(true, jujuUser)
}

func cmdJujuUsersPost(s *state.State, r *http.Request) response.Response {
func cmdJujuUsersPost(s state.State, r *http.Request) response.Response {
var req types.JujuUser

err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
return response.InternalError(err)
}

err = sunbeam.AddJujuUser(s, req.Username, req.Token)
err = sunbeam.AddJujuUser(r.Context(), s, req.Username, req.Token)
if err != nil {
return response.InternalError(err)
}

return response.EmptySyncResponse
}

func cmdJujuUsersDelete(s *state.State, r *http.Request) response.Response {
func cmdJujuUsersDelete(s state.State, r *http.Request) response.Response {
name, err := url.PathUnescape(mux.Vars(r)["name"])
if err != nil {
return response.SmartError(err)
}
err = sunbeam.DeleteJujuUser(s, name)
err = sunbeam.DeleteJujuUser(r.Context(), s, name)
if err != nil {
return response.InternalError(err)
}
Expand Down
20 changes: 10 additions & 10 deletions sunbeam-microcluster/api/manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (

"github.com/canonical/lxd/lxd/response"
"github.com/canonical/lxd/shared/api"
"github.com/canonical/microcluster/rest"
"github.com/canonical/microcluster/state"
"github.com/canonical/microcluster/v2/rest"
"github.com/canonical/microcluster/v2/state"
"github.com/gorilla/mux"

"github.com/canonical/snap-openstack/sunbeam-microcluster/access"
Expand All @@ -33,23 +33,23 @@ var manifestCmd = rest.Endpoint{
Delete: access.ClusterCATrustedEndpoint(cmdManifestDelete, true),
}

func cmdManifestsGetAll(s *state.State, _ *http.Request) response.Response {
func cmdManifestsGetAll(s state.State, r *http.Request) response.Response {

manifests, err := sunbeam.ListManifests(s)
manifests, err := sunbeam.ListManifests(r.Context(), s)
if err != nil {
return response.InternalError(err)
}

return response.SyncResponse(true, manifests)
}

func cmdManifestGet(s *state.State, r *http.Request) response.Response {
func cmdManifestGet(s state.State, r *http.Request) response.Response {
var manifestid string
manifestid, err := url.PathUnescape(mux.Vars(r)["manifestid"])
if err != nil {
return response.InternalError(err)
}
manifest, err := sunbeam.GetManifest(s, manifestid)
manifest, err := sunbeam.GetManifest(r.Context(), s, manifestid)
if err != nil {
if err, ok := err.(api.StatusError); ok {
if err.Status() == http.StatusNotFound {
Expand All @@ -62,28 +62,28 @@ func cmdManifestGet(s *state.State, r *http.Request) response.Response {
return response.SyncResponse(true, manifest)
}

func cmdManifestsPost(s *state.State, r *http.Request) response.Response {
func cmdManifestsPost(s state.State, r *http.Request) response.Response {
var req types.Manifest

err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
return response.InternalError(err)
}

err = sunbeam.AddManifest(s, req.ManifestID, req.Data)
err = sunbeam.AddManifest(r.Context(), s, req.ManifestID, req.Data)
if err != nil {
return response.InternalError(err)
}

return response.EmptySyncResponse
}

func cmdManifestDelete(s *state.State, r *http.Request) response.Response {
func cmdManifestDelete(s state.State, r *http.Request) response.Response {
manifestid, err := url.PathUnescape(mux.Vars(r)["manifestid"])
if err != nil {
return response.SmartError(err)
}
err = sunbeam.DeleteManifest(s, manifestid)
err = sunbeam.DeleteManifest(r.Context(), s, manifestid)
if err != nil {
return response.InternalError(err)
}
Expand Down
Loading

0 comments on commit 4446142

Please sign in to comment.