Skip to content

Commit

Permalink
Merge pull request #36 from AcalephStorage/release/0.1.2
Browse files Browse the repository at this point in the history
Release 0.1.2
  • Loading branch information
darkcrux committed May 10, 2016
2 parents 6838699 + 26206f4 commit 2dfa32e
Show file tree
Hide file tree
Showing 22 changed files with 796 additions and 303 deletions.
5 changes: 1 addition & 4 deletions .pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ spec:
app: kontinuous
type: ci-cd
secrets:
- docker-credentials
- quayregistrycreds
stages:
- name: Build Docker Image
type: docker_build
Expand All @@ -32,6 +32,3 @@ spec:
external_registry: quay.io
external_image_name: acaleph/kontinuous
require_credentials: "TRUE"
username: user
password: password
email: email
15 changes: 12 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.6
FROM golang:1.6-alpine

ENV GOPATH /go
ENV SWAGGER_UI /swagger/dist
Expand All @@ -9,6 +9,15 @@ WORKDIR /go/src/github.com/AcalephStorage/kontinuous
RUN mkdir /swagger && tar xvzf third_party/swagger.tar.gz -C /swagger

# create and remove downloaded libraries
RUN make && rm -rf /go/bin && rm -rf /go/lib
RUN apk update && \
apk add make git && \
make && \
mv build/bin/kontinuous /bin && \
mv build/bin/kontinuous-cli /bin && \
rm -rf /go && \
apk del --purge make git && \
rm -rf /var/cache/apk/*

ENTRYPOINT build/bin/kontinuous
EXPOSE 3005

ENTRYPOINT /bin/kontinuous
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Alternatively, for more customization, a sample yaml file for running kontinuous

Once running, add a [.pipeline.yml](#pipeline-spec) to the root of your Github repo and configure the webhooks.

Example pipelines can be found in [/examples](./examples)

The [CLI client](#clients) or [API](#api) can be used to view build status or logs.

### Dependencies
Expand Down Expand Up @@ -78,7 +80,7 @@ The following environment variables needs to be defined:

A Kubernetes Secret also needs to be defined and mounted to the Pod. The secret should have a key named `kontinuous-secrets` and should contain the following data (must be base64 encoded):

```
```json
{
"AuthSecret": "base64 encoded auth secret",
"S3SecretKey": "s3 secret key",
Expand All @@ -102,7 +104,7 @@ The repository needs to define a build pipeline in the repository root called `.

Here's a sample `.pipeline.yml`:

```
```yaml
---
apiVersion: v1alpha1
kind: Pipeline
Expand Down Expand Up @@ -157,7 +159,7 @@ The format is something similar to K8s Specs. Here are more details on some of t

The general definition of a stage is:

```
```yaml
name: Friendly name
type: {docker_build,command,docker_publish}
params:
Expand Down Expand Up @@ -242,9 +244,9 @@ Make sure to enable access to the following:

The script `scripts/jwt-gen` can generate a JSON Web Token to be used for authentication with Kontinuous.

```
```console
$ scripts/jwt-gen --secret {base64url encoded secret} --github-token {github-token}
```
```

This generates a JSON Web Token and can be added to the request header as `Authorization: Bearer {token}` to authenticate requests.

Expand All @@ -266,13 +268,13 @@ A Web based Dashboard is under development.

Building `kontinuous` from source is done by:

```
```console
$ make deps build
```

Build the docker image:

```
```console
$ docker build -t {tag} .
```

Expand Down
124 changes: 124 additions & 0 deletions api/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,42 @@ package api

import (
"errors"
"fmt"
"os"
"strings"

"encoding/base64"
"encoding/json"
"io/ioutil"
"net/http"
"net/url"

"github.com/dgrijalva/jwt-go"
"github.com/emicklei/go-restful"

"github.com/AcalephStorage/kontinuous/pipeline"
"github.com/AcalephStorage/kontinuous/store/kv"
)

type GithubAuthResponse struct {
AccessToken string `json:"access_token"`
}

// JWTClaims contains the claims from the jwt
type JWTClaims struct {
GithubAccessToken string
}

type AuthResource struct {
JWTClaims
kv.KVClient
}

type AuthResponse struct {
JWT string `json:"jwt"`
UserID string `json:"user_id"`
}

var (
claims JWTClaims

Expand Down Expand Up @@ -58,6 +79,109 @@ var (
}
)

func (a *AuthResource) Register(container *restful.Container) {
ws := new(restful.WebService)

ws.
Path("/login").
Consumes(restful.MIME_JSON).
Produces(restful.MIME_JSON).
Filter(ncsaCommonLogFormatLogger)

ws.Route(ws.POST("github").To(a.githubLogin).
Writes(AuthResponse{}).
Doc("Generate JWT for API authentication").
Operation("authorize"))

container.Add(ws)
}

func (a *AuthResource) githubLogin(req *restful.Request, res *restful.Response) {

dsecret := os.Getenv("AUTH_SECRET")

authCode := req.QueryParameter("code")
state := req.QueryParameter("state")

if len(authCode) == 0 {
jsonError(res, http.StatusUnauthorized, errors.New("Missing Authorization Code"), "No authorization code provided")
return
}

// request url
reqUrl := url.URL{
Scheme: "https",
Host: "github.com",
Path: "login/oauth/access_token",
}
q := reqUrl.Query()
q.Set("client_id", os.Getenv("GH_CLIENT_ID"))
q.Set("client_secret", os.Getenv("GH_CLIENT_SECRET"))
q.Set("code", authCode)
q.Set("state", state)
reqUrl.RawQuery = q.Encode()

client := &http.Client{}

r, err := http.NewRequest("POST", reqUrl.String(), nil)
if err != nil {
jsonError(res, http.StatusUnauthorized, err, "Error creating auth request")
return
}
r.Header.Add("Accept", "application/json")

authRes, err := client.Do(r)
if err != nil {
jsonError(res, http.StatusUnauthorized, err, "Error requesting authorization token")
return
}
defer authRes.Body.Close()

body, err := ioutil.ReadAll(authRes.Body)
if err != nil {
jsonError(res, http.StatusUnauthorized, err, "Error reading response body")
return
}

var ghRes GithubAuthResponse
if err := json.Unmarshal(body, &ghRes); err != nil {
jsonError(res, http.StatusUnauthorized, err, "Error reading json body")
return
}

accessToken := ghRes.AccessToken

jwtToken, err := CreateJWT(accessToken, string(dsecret))
if err != nil {
jsonError(res, http.StatusUnauthorized, err, "Unable to create jwt for user")
return
}

ghUser, err := GetGithubUser(accessToken)
if err != nil {
jsonError(res, http.StatusUnauthorized, err, "Unable to get github user")
return
}

userID := fmt.Sprintf("github|%v", ghUser.ID)
user := &pipeline.User{
Name: ghUser.Login,
RemoteID: userID,
Token: accessToken,
}
if err := user.Save(a.KVClient); err != nil {
jsonError(res, http.StatusUnauthorized, err, "Unable to register user")
return
}

entity := &AuthResponse{
JWT: jwtToken,
UserID: userID,
}

res.WriteEntity(entity)
}

func parseToken(req *restful.Request) string {
// apply the same checking as jwt.ParseFromRequest
if ah := req.HeaderParameter("Authorization"); ah != "" {
Expand Down
15 changes: 10 additions & 5 deletions api/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package api
import (
"errors"
"fmt"
"strconv"
"time"

"encoding/json"
Expand Down Expand Up @@ -100,6 +99,12 @@ func (b *BuildResource) create(req *restful.Request, res *restful.Response) {
return
}

//check if .pipeline exist in branch
if _, err := pipeline.Definition(hook.Commit, client); err != nil {
jsonError(res, http.StatusInternalServerError, err, "Unable to create build. pipeline")
return
}

// persist build
build := &ps.Build{
Author: hook.Author,
Expand All @@ -122,8 +127,8 @@ func (b *BuildResource) create(req *restful.Request, res *restful.Response) {
return
}

//save notif details in pipeline
pipeline.SaveNotifiers(definition, b.KVClient)
//update details in pipeline
pipeline.UpdatePipeline(definition, b.KVClient)

// save stage details
build.Stages = definition.GetStages()
Expand All @@ -135,7 +140,7 @@ func (b *BuildResource) create(req *restful.Request, res *restful.Response) {

stageStatus := &ps.StatusUpdate{
Status: ps.BuildFailure,
Timestamp: strconv.FormatInt(time.Now().UnixNano(), 10),
Timestamp: time.Now().UnixNano(),
}
stage, err := findStage("1", build, b.KVClient)
if err != nil {
Expand Down Expand Up @@ -181,7 +186,7 @@ func (b *BuildResource) list(req *restful.Request, res *restful.Response) {
return
}

builds, err := pipeline.GetBuilds(b.KVClient)
builds, err := pipeline.GetAllBuildsSummary(b.KVClient)
if err != nil {
jsonError(res, http.StatusInternalServerError, err, fmt.Sprintf("Unable to list builds for %s/%s", owner, repo))
return
Expand Down
Loading

0 comments on commit 2dfa32e

Please sign in to comment.