From e52329b1116d14a0e447956b90f37e815be0f89b Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Thu, 28 Feb 2019 12:49:04 -0800 Subject: [PATCH] adde encrypt endpoint --- cmd/drone-server/bootstrap/bootstrap_test.go | 2 +- handler/api/api.go | 6 ++ handler/api/badge/badge.go | 23 +++++ handler/api/badge/status.go | 10 +-- handler/api/badge/status_oss.go | 37 ++++++++ handler/api/badge/status_test.go | 4 +- handler/api/ccmenu/cc.go | 2 + handler/api/ccmenu/cc_test.go | 2 + handler/api/ccmenu/ccmenu.go | 2 + handler/api/ccmenu/ccmenu_oss.go | 31 +++++++ handler/api/ccmenu/ccmenu_test.go | 4 +- handler/api/repos/encrypt/encrypt.go | 91 ++++++++++++++++++++ handler/api/repos/encrypt/encrypt_test.go | 1 + store/shared/db/conn.go | 2 + store/shared/db/conn_oss.go | 42 +++++++++ store/shared/db/db.go | 16 +++- store/shared/db/error.go | 16 +++- store/shared/db/nop.go | 16 +++- store/shared/encrypt/aesgcm.go | 16 +++- store/shared/encrypt/encrypt.go | 16 +++- store/shared/encrypt/none.go | 16 +++- store/shared/migrate/sqlite/ddl.go | 16 +++- 22 files changed, 339 insertions(+), 32 deletions(-) create mode 100644 handler/api/badge/badge.go create mode 100644 handler/api/badge/status_oss.go create mode 100644 handler/api/ccmenu/ccmenu_oss.go create mode 100644 handler/api/repos/encrypt/encrypt.go create mode 100644 handler/api/repos/encrypt/encrypt_test.go create mode 100644 store/shared/db/conn_oss.go diff --git a/cmd/drone-server/bootstrap/bootstrap_test.go b/cmd/drone-server/bootstrap/bootstrap_test.go index 142857be..02dfb7b6 100644 --- a/cmd/drone-server/bootstrap/bootstrap_test.go +++ b/cmd/drone-server/bootstrap/bootstrap_test.go @@ -10,8 +10,8 @@ import ( "io/ioutil" "testing" - "github.com/drone/drone/mock" "github.com/drone/drone/core" + "github.com/drone/drone/mock" "github.com/dchest/uniuri" "github.com/golang/mock/gomock" diff --git a/handler/api/api.go b/handler/api/api.go index 01f81e5d..aeeb8d1d 100644 --- a/handler/api/api.go +++ b/handler/api/api.go @@ -31,6 +31,7 @@ import ( "github.com/drone/drone/handler/api/repos/builds/stages" "github.com/drone/drone/handler/api/repos/collabs" "github.com/drone/drone/handler/api/repos/crons" + "github.com/drone/drone/handler/api/repos/encrypt" "github.com/drone/drone/handler/api/repos/secrets" "github.com/drone/drone/handler/api/repos/sign" "github.com/drone/drone/handler/api/system" @@ -214,6 +215,11 @@ func (s Server) Handler() http.Handler { r.Post("/", sign.HandleSign(s.Repos)) }) + r.Route("/encrypt", func(r chi.Router) { + r.Use(acl.CheckWriteAccess()) + r.Post("/", encrypt.Handler(s.Repos)) + }) + r.Route("/cron", func(r chi.Router) { r.Use(acl.CheckWriteAccess()) r.Post("/", crons.HandleCreate(s.Repos, s.Cron)) diff --git a/handler/api/badge/badge.go b/handler/api/badge/badge.go new file mode 100644 index 00000000..1152dd54 --- /dev/null +++ b/handler/api/badge/badge.go @@ -0,0 +1,23 @@ +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package badge + +var ( + badgeSuccess = `buildbuildsuccesssuccess` + badgeFailure = `buildbuildfailurefailure` + badgeStarted = `buildbuildstartedstarted` + badgeError = `buildbuilderrorerror` + badgeNone = `buildbuildnonenone` +) diff --git a/handler/api/badge/status.go b/handler/api/badge/status.go index 576e175c..db395635 100644 --- a/handler/api/badge/status.go +++ b/handler/api/badge/status.go @@ -2,6 +2,8 @@ // Use of this source code is governed by the Drone Non-Commercial License // that can be found in the LICENSE file. +// +build !oss + package badge import ( @@ -15,14 +17,6 @@ import ( "github.com/go-chi/chi" ) -var ( - badgeSuccess = `buildbuildsuccesssuccess` - badgeFailure = `buildbuildfailurefailure` - badgeStarted = `buildbuildstartedstarted` - badgeError = `buildbuilderrorerror` - badgeNone = `buildbuildnonenone` -) - // Handler returns an http.HandlerFunc that writes an svg status // badge to the response. func Handler( diff --git a/handler/api/badge/status_oss.go b/handler/api/badge/status_oss.go new file mode 100644 index 00000000..2bde2dc0 --- /dev/null +++ b/handler/api/badge/status_oss.go @@ -0,0 +1,37 @@ +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build oss + +package badge + +import ( + "io" + "net/http" + "time" + + "github.com/drone/drone/core" +) + +// Handler returns a no-op http.HandlerFunc. +func Handler(core.RepositoryStore, core.BuildStore) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value") + w.Header().Set("Expires", "Thu, 01 Jan 1970 00:00:00 GMT") + w.Header().Set("Last-Modified", time.Now().UTC().Format(http.TimeFormat)) + w.Header().Set("Content-Type", "image/svg+xml") + io.WriteString(w, badgeNone) + } +} diff --git a/handler/api/badge/status_test.go b/handler/api/badge/status_test.go index 3d15999e..d8da8b82 100644 --- a/handler/api/badge/status_test.go +++ b/handler/api/badge/status_test.go @@ -2,6 +2,8 @@ // Use of this source code is governed by the Drone Non-Commercial License // that can be found in the LICENSE file. +// +build !oss + package badge import ( @@ -10,8 +12,8 @@ import ( "net/http/httptest" "testing" - "github.com/drone/drone/mock" "github.com/drone/drone/core" + "github.com/drone/drone/mock" "github.com/go-chi/chi" "github.com/golang/mock/gomock" diff --git a/handler/api/ccmenu/cc.go b/handler/api/ccmenu/cc.go index baca5ba2..cf4da566 100644 --- a/handler/api/ccmenu/cc.go +++ b/handler/api/ccmenu/cc.go @@ -2,6 +2,8 @@ // Use of this source code is governed by the Drone Non-Commercial License // that can be found in the LICENSE file. +// +build !oss + package ccmenu import ( diff --git a/handler/api/ccmenu/cc_test.go b/handler/api/ccmenu/cc_test.go index abf49e14..fe06e849 100644 --- a/handler/api/ccmenu/cc_test.go +++ b/handler/api/ccmenu/cc_test.go @@ -2,6 +2,8 @@ // Use of this source code is governed by the Drone Non-Commercial License // that can be found in the LICENSE file. +// +build !oss + package ccmenu import ( diff --git a/handler/api/ccmenu/ccmenu.go b/handler/api/ccmenu/ccmenu.go index 55d2c090..02ae5482 100644 --- a/handler/api/ccmenu/ccmenu.go +++ b/handler/api/ccmenu/ccmenu.go @@ -2,6 +2,8 @@ // Use of this source code is governed by the Drone Non-Commercial License // that can be found in the LICENSE file. +// +build !oss + package ccmenu import ( diff --git a/handler/api/ccmenu/ccmenu_oss.go b/handler/api/ccmenu/ccmenu_oss.go new file mode 100644 index 00000000..7beb3796 --- /dev/null +++ b/handler/api/ccmenu/ccmenu_oss.go @@ -0,0 +1,31 @@ +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build oss + +package ccmenu + +import ( + "net/http" + + "github.com/drone/drone/core" + "github.com/drone/drone/handler/api/render" +) + +// Handler returns a no-op http.HandlerFunc. +func Handler(core.RepositoryStore, core.BuildStore, string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + render.NotImplemented(w, render.ErrNotImplemented) + } +} diff --git a/handler/api/ccmenu/ccmenu_test.go b/handler/api/ccmenu/ccmenu_test.go index 1f20a8b2..8b133136 100644 --- a/handler/api/ccmenu/ccmenu_test.go +++ b/handler/api/ccmenu/ccmenu_test.go @@ -2,6 +2,8 @@ // Use of this source code is governed by the Drone Non-Commercial License // that can be found in the LICENSE file. +// +build !oss + package ccmenu import ( @@ -11,8 +13,8 @@ import ( "net/http/httptest" "testing" - "github.com/drone/drone/mock" "github.com/drone/drone/core" + "github.com/drone/drone/mock" "github.com/go-chi/chi" "github.com/golang/mock/gomock" diff --git a/handler/api/repos/encrypt/encrypt.go b/handler/api/repos/encrypt/encrypt.go new file mode 100644 index 00000000..55a1aa1c --- /dev/null +++ b/handler/api/repos/encrypt/encrypt.go @@ -0,0 +1,91 @@ +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package encrypt + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "encoding/json" + "io" + "net/http" + + "github.com/drone/drone-go/drone" + "github.com/drone/drone/core" + "github.com/drone/drone/handler/api/render" + "github.com/go-chi/chi" +) + +type respEncrypted struct { + Data string `json:"data"` +} + +// Handler returns an http.HandlerFunc that processes http +// requests to create an encrypted secret. +func Handler(repos core.RepositoryStore) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + namespace := chi.URLParam(r, "owner") + name := chi.URLParam(r, "name") + repo, err := repos.FindName(r.Context(), namespace, name) + if err != nil { + render.NotFound(w, err) + return + } + + in := new(drone.Secret) + err = json.NewDecoder(r.Body).Decode(in) + if err != nil { + render.BadRequest(w, err) + return + } + + // the secret is encrypted with a per-repository 256-bit + // key. If the key is missing or malformed we should + // return an error to the client. + encrypted, err := encrypt([]byte(in.Data), []byte(repo.Secret)) + if err != nil { + render.InternalError(w, err) + return + } + + // the encrypted secret is embedded in the yaml + // configuration file and is json-encoded for + // inclusion as a !binary attribute. + encoded := base64.URLEncoding.EncodeToString(encrypted) + + render.JSON(w, &respEncrypted{Data: encoded}, 200) + } +} + +func encrypt(plaintext, key []byte) (ciphertext []byte, err error) { + block, err := aes.NewCipher(key[:]) + if err != nil { + return nil, err + } + + gcm, err := cipher.NewGCM(block) + if err != nil { + return nil, err + } + + nonce := make([]byte, gcm.NonceSize()) + _, err = io.ReadFull(rand.Reader, nonce) + if err != nil { + return nil, err + } + + return gcm.Seal(nonce, nonce, plaintext, nil), nil +} diff --git a/handler/api/repos/encrypt/encrypt_test.go b/handler/api/repos/encrypt/encrypt_test.go new file mode 100644 index 00000000..7e5445a8 --- /dev/null +++ b/handler/api/repos/encrypt/encrypt_test.go @@ -0,0 +1 @@ +package encrypt diff --git a/store/shared/db/conn.go b/store/shared/db/conn.go index 5fce9b0e..7b53513b 100644 --- a/store/shared/db/conn.go +++ b/store/shared/db/conn.go @@ -2,6 +2,8 @@ // Use of this source code is governed by the Drone Non-Commercial License // that can be found in the LICENSE file. +// +build !oss + package db import ( diff --git a/store/shared/db/conn_oss.go b/store/shared/db/conn_oss.go new file mode 100644 index 00000000..e401bd66 --- /dev/null +++ b/store/shared/db/conn_oss.go @@ -0,0 +1,42 @@ +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build oss + +package db + +import ( + "database/sql" + "sync" + + "github.com/jmoiron/sqlx" + + "github.com/drone/drone/store/shared/migrate/sqlite" +) + +// Connect to an embedded sqlite database. +func Connect(driver, datasource string) (*DB, error) { + db, err := sql.Open(driver, datasource) + if err != nil { + return nil, err + } + if err := sqlite.Migrate(db); err != nil { + return nil, err + } + return &DB{ + conn: sqlx.NewDb(db, driver), + lock: &sync.RWMutex{}, + driver: Sqlite, + }, nil +} diff --git a/store/shared/db/db.go b/store/shared/db/db.go index 76becb2f..2d36b4af 100644 --- a/store/shared/db/db.go +++ b/store/shared/db/db.go @@ -1,6 +1,16 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Drone Non-Commercial License -// that can be found in the LICENSE file. +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package db diff --git a/store/shared/db/error.go b/store/shared/db/error.go index 9bb242d7..91308e39 100644 --- a/store/shared/db/error.go +++ b/store/shared/db/error.go @@ -1,6 +1,16 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Drone Non-Commercial License -// that can be found in the LICENSE file. +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package db diff --git a/store/shared/db/nop.go b/store/shared/db/nop.go index bb777bba..85f60eb7 100644 --- a/store/shared/db/nop.go +++ b/store/shared/db/nop.go @@ -1,6 +1,16 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Drone Non-Commercial License -// that can be found in the LICENSE file. +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package db diff --git a/store/shared/encrypt/aesgcm.go b/store/shared/encrypt/aesgcm.go index 46c821d2..a038b333 100644 --- a/store/shared/encrypt/aesgcm.go +++ b/store/shared/encrypt/aesgcm.go @@ -1,6 +1,16 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Drone Non-Commercial License -// that can be found in the LICENSE file. +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package encrypt diff --git a/store/shared/encrypt/encrypt.go b/store/shared/encrypt/encrypt.go index c06a0000..0a4f36ed 100644 --- a/store/shared/encrypt/encrypt.go +++ b/store/shared/encrypt/encrypt.go @@ -1,6 +1,16 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Drone Non-Commercial License -// that can be found in the LICENSE file. +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package encrypt diff --git a/store/shared/encrypt/none.go b/store/shared/encrypt/none.go index 052fac05..b780d6cf 100644 --- a/store/shared/encrypt/none.go +++ b/store/shared/encrypt/none.go @@ -1,6 +1,16 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Drone Non-Commercial License -// that can be found in the LICENSE file. +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package encrypt diff --git a/store/shared/migrate/sqlite/ddl.go b/store/shared/migrate/sqlite/ddl.go index 4fd1b058..48b3d8b7 100644 --- a/store/shared/migrate/sqlite/ddl.go +++ b/store/shared/migrate/sqlite/ddl.go @@ -1,6 +1,16 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Drone Non-Commercial License -// that can be found in the LICENSE file. +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package sqlite