コード例 #1
0
ファイル: rotate.go プロジェクト: realglobe-Inc/go-lib
func rotateFile(path string, num int) error {
	var n int

	for n = 1; n < num; n++ {
		_, err := os.Stat(path + "." + strconv.Itoa(n))
		if err == nil {
			continue
		} else if os.IsNotExist(err) {
			break
		} else {
			return erro.Wrap(err)
		}
	}
	n--

	// .{n} が残す中で一番最後。

	// .{i} を .{i+1} に。
	for ; n > 0; n-- {
		from := path + "." + strconv.Itoa(n)
		to := path + "." + strconv.Itoa(n+1)
		if err := os.Rename(from, to); err != nil {
			return erro.Wrap(err)
		}
	}

	// 最新版 を .1 に。
	if err := os.Rename(path, path+".1"); err != nil {
		return erro.Wrap(err)
	}

	return nil
}
コード例 #2
0
ファイル: fluentd.go プロジェクト: realglobe-Inc/go-lib
func (core *fluentdCoreHandler) flushCore(writeSize int) {
	for retry := false; ; retry = true {
		if core.conn == nil {
			var err error
			core.conn, err = net.Dial("tcp", core.addr)
			if err != nil {
				// 接続出来なければ諦める。
				fmt.Fprintln(os.Stderr, erro.Wrap(err))
				return
			}
			core.buff.setSink(core.conn)
		}

		// 接続はある。

		err := core.buff.flushIfNeeded(writeSize)
		if err == nil {
			// 書き込み成功。
			return
		}

		// 書き込み失敗。
		// 接続が古くてサーバー側に切断されていたとか。

		fmt.Fprintln(os.Stderr, erro.Wrap(err))
		core.conn.Close()
		core.conn = nil

		if retry {
			// 接続しなおしても書き込めないなら諦める。
			return
		}
	}
}
コード例 #3
0
ファイル: code_token.go プロジェクト: realglobe-Inc/edo-auth
func parseCodeToken(raw []byte) (*codeToken, error) {
	base, err := jwt.Parse(raw)
	if err != nil {
		return nil, erro.Wrap(err)
	}
	var buff struct {
		Idp      string            `json:"iss"`
		Cod      string            `json:"sub"`
		Aud      audience.Audience `json:"aud"`
		FrTa     string            `json:"from_client"`
		AcntTag  string            `json:"user_tag"`
		AcntTags strset.Set        `json:"user_tags"`
		RefHash  string            `json:"ref_hash"`
	}
	if err := json.Unmarshal(base.RawBody(), &buff); err != nil {
		return nil, erro.Wrap(err)
	} else if buff.Idp == "" {
		return nil, erro.New("no ID provider ID")
	} else if buff.Cod == "" {
		return nil, erro.New("no code")
	} else if len(buff.Aud) == 0 {
		return nil, erro.New("no audience")
	}

	return &codeToken{
		base:     base,
		idp:      buff.Idp,
		cod:      buff.Cod,
		aud:      buff.Aud,
		frTa:     buff.FrTa,
		acntTag:  buff.AcntTag,
		acntTags: buff.AcntTags,
		refHash:  buff.RefHash,
	}, nil
}
コード例 #4
0
ファイル: values_test.go プロジェクト: realglobe-Inc/edo-auth
func newTestSingleRequestWithParams(hndl *handler, idp idpdb.Element, params map[string]interface{}) (*http.Request, error) {
	r, err := http.NewRequest("GET", "http://localhost/coop", nil)
	if err != nil {
		return nil, erro.Wrap(err)
	}

	codTok := jwt.New()
	codTok.SetHeader("alg", test_idpSigAlg)
	codTok.SetClaim("iss", idp.Id())
	codTok.SetClaim("sub", test_cod)
	codTok.SetClaim("aud", audience.New(hndl.selfId))
	codTok.SetClaim("from_client", test_frTa.Id())
	codTok.SetClaim("user_tag", test_acntTag)
	codTok.SetClaim("user_tags", []string{test_subAcnt1Tag})
	for k, v := range params {
		codTok.SetClaim(k, v)
	}
	if err := codTok.Sign(idp.Keys()); err != nil {
		return nil, erro.Wrap(err)
	}
	data, err := codTok.Encode()
	if err != nil {
		return nil, erro.Wrap(err)
	}
	r.Header.Set("X-Edo-Code-Tokens", string(data))

	return r, nil
}
コード例 #5
0
ファイル: main_test.go プロジェクト: realglobe-Inc/edo-auth
func setupKeyDb(path string, keys []jwk.Key) (dir string, err error) {
	dir, err = ioutil.TempDir(filepath.Dir(path), filepath.Base(path))
	for i, key := range keys {
		if data, err := json.Marshal(key.ToMap()); err != nil {
			return "", erro.Wrap(err)
		} else if ioutil.WriteFile(filepath.Join(dir, strconv.Itoa(i)+".json"), data, 0644); err != nil {
			return "", erro.Wrap(err)
		}
	}
	return dir, nil
}
コード例 #6
0
ファイル: simple.go プロジェクト: realglobe-Inc/go-lib
func NewFileHandlerUsing(path string, fmter Formatter) (Handler, error) {
	if err := os.MkdirAll(filepath.Dir(path), dirPerm); err != nil {
		return nil, erro.Wrap(err)
	}
	// file の Close はプログラムの終処理任せ。
	sink, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, filePerm)
	if err != nil {
		return nil, erro.Wrap(err)
	}
	return NewCloseHandlerUsing(sink, fmter), nil
}
コード例 #7
0
ファイル: lock_linux.go プロジェクト: realglobe-Inc/go-lib
// 解放する。
func (lock *Locker) Unlock() error {
	file := (*os.File)(lock)
	if err := syscall.Flock(int(file.Fd()), syscall.LOCK_UN); err != nil {
		return erro.Wrap(err)
	}
	if err := file.Close(); err != nil {
		return erro.Wrap(err)
	}

	return nil
}
コード例 #8
0
ファイル: values_test.go プロジェクト: realglobe-Inc/edo-auth
func newTestMainIdpResponseWithParams(hndl *handler, idp idpdb.Element, params, idsTokParams map[string]interface{}) (status int, header http.Header, body []byte, err error) {
	now := time.Now()

	idsTok := jwt.New()
	idsTok.SetHeader("alg", test_idpSigAlg)
	idsTok.SetClaim("iss", idp.Id())
	idsTok.SetClaim("sub", test_frTa.Id())
	idsTok.SetClaim("aud", audience.New(hndl.selfId))
	idsTok.SetClaim("exp", now.Add(time.Minute).Unix())
	idsTok.SetClaim("iat", now.Unix())
	idsTok.SetClaim("ids", map[string]map[string]interface{}{
		test_acntTag: {
			"sub":   test_acntId,
			"email": test_acntEmail,
		},
		test_subAcnt1Tag: {
			"sub":   test_subAcnt1Id,
			"email": test_subAcnt1Email,
		},
	})
	for k, v := range idsTokParams {
		idsTok.SetClaim(k, v)
	}
	if err := idsTok.Sign(idp.Keys()); err != nil {
		return 0, nil, nil, erro.Wrap(err)
	}
	data, err := idsTok.Encode()
	if err != nil {
		return 0, nil, nil, erro.Wrap(err)
	}

	m := map[string]interface{}{
		"access_token": test_tok,
		"token_type":   "Bearer",
		"expires_in":   1234,
		"scope":        "openid email",
		"ids_token":    string(data),
	}
	for k, v := range params {
		if v == nil {
			delete(m, k)
		} else {
			m[k] = v
		}
	}
	body, err = json.Marshal(m)
	if err != nil {
		return 0, nil, nil, erro.Wrap(err)
	}

	return http.StatusOK, http.Header{"Content-Type": {"application/json"}}, body, nil
}
コード例 #9
0
ファイル: rotate_test.go プロジェクト: realglobe-Inc/go-lib
func testFilePath() (path string, err error) {
	file, err := ioutil.TempFile("", "test_")
	if err != nil {
		return "", erro.Wrap(err)
	}
	if err := file.Close(); err != nil {
		return "", erro.Wrap(err)
	}
	if err := os.Remove(file.Name()); err != nil {
		return "", erro.Wrap(err)
	}
	return file.Name(), nil
}
コード例 #10
0
ファイル: syslog.go プロジェクト: realglobe-Inc/go-lib
func (core *syslogCoreHandler) output(rec Record) {
	// {レベル} {ファイル名}:{行番号} {メッセージ}
	// 日時は syslog が付ける。
	msg := fmt.Sprintf("%."+strconv.Itoa(lvWidth)+"v %s:%d %s\n",
		rec.Level(), rec.File(), rec.Line(), rec.Message())

	for retry := false; ; retry = true {
		if core.base == nil {
			var err error
			core.base, err = syslog.Dial("", core.addr, syslog.LOG_INFO, core.tag)
			if err != nil {
				// 初期化出来なければ諦める。
				fmt.Fprintln(os.Stderr, erro.Wrap(err))
				fmt.Fprintln(os.Stderr, "Drop log: "+string(SimpleFormatter.Format(rec)))
				return
			}
		}

		// 初期化してある。

		var err error
		switch rec.Level() {
		case level.ERR:
			err = core.base.Err(msg)
		case level.WARN:
			err = core.base.Warning(msg)
		case level.INFO:
			err = core.base.Info(msg)
		case level.DEBUG:
			err = core.base.Debug(msg)
		}
		if err == nil {
			// 書き込み成功。
			return
		}

		// 書き込み失敗。
		// 初期化が古くてサーバー側で何か変わったとか。

		fmt.Fprintln(os.Stderr, erro.Wrap(err))
		core.base.Close()
		core.base = nil

		if retry {
			// 初期化しなおしても書き込めないなら諦める。
			fmt.Fprintln(os.Stderr, "Drop log: "+string(SimpleFormatter.Format(rec)))
			return
		}
	}
}
コード例 #11
0
ファイル: rotate.go プロジェクト: realglobe-Inc/go-lib
func (core *rotateCoreHandler) flushCore(writeSize int) {
	// ロックファイルをつくったほうが良いが、OS 依存なので止めとく。

	for {
		if core.file == nil {
			// ファイルを開く。
			if err := os.MkdirAll(filepath.Dir(core.path), dirPerm); err != nil {
				fmt.Fprintln(os.Stderr, erro.Wrap(err))
				return
			}

			var err error
			core.file, err = os.OpenFile(core.path, os.O_RDWR|os.O_APPEND|os.O_CREATE, filePerm)
			if err != nil {
				fmt.Fprintln(os.Stderr, erro.Wrap(err))
				return
			}

			if err := core.buff.setSink(core.file); err != nil {
				fmt.Fprintln(os.Stderr, erro.Wrap(err))
				return
			}
		}

		// ファイルを開いている。

		err := core.buff.flushIfNeeded(writeSize)
		switch err {
		case nil:
			// 書き込み成功。
			return
		case fileIsFull:
			// ローテートする。
			core.file.Close()
			core.file = nil
			if err := rotateFile(core.path, core.num); err != nil {
				fmt.Fprintln(os.Stderr, erro.Wrap(err))
				return
			}
			continue
		default:
			fmt.Fprintln(os.Stderr, erro.Wrap(err))
			core.file.Close()
			core.file = nil
			return
		}
	}
}
コード例 #12
0
// 保存。
func (this *redisDb) Save(elem *Element, exp time.Time) error {
	conn := this.pool.Get()
	defer conn.Close()

	data, err := json.Marshal(elem)
	if err != nil {
		return erro.Wrap(err)
	}
	expIn := int64(exp.Sub(time.Now()) / time.Millisecond)

	if _, err := conn.Do("SET", this.tag+elem.Tag(), data, "PX", expIn); err != nil {
		return erro.Wrap(err)
	}

	return nil
}
コード例 #13
0
func parseCoopResponse(resp *http.Response) (*coopResponse, error) {
	if resp.StatusCode != http.StatusOK {
		return nil, erro.New("invalid state ", resp.StatusCode)
	} else if contType := resp.Header.Get(tagContent_type); contType != contTypeJson {
		return nil, erro.New("invalid content type " + contType)
	}

	var buff struct {
		Tok     string `json:"access_token"`
		TokType string `json:"token_type"`
		ExpIn   int    `json:"expires_in"`
		Scop    string `json:"scope"`
		IdsTok  string `json:"ids_token"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&buff); err != nil {
		return nil, erro.Wrap(err)
	} else if buff.IdsTok == "" {
		return nil, erro.New("cannot get IDs token")
	}

	return &coopResponse{
		tok:     buff.Tok,
		tokType: buff.TokType,
		expIn:   time.Duration(buff.ExpIn) * time.Second,
		scop:    requtil.FormValueSet(buff.Scop),
		idsTok:  []byte(buff.IdsTok),
	}, nil
}
コード例 #14
0
ファイル: handler.go プロジェクト: realglobe-Inc/edo-auth
func (this *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var logPref string

	// panic 対策。
	defer func() {
		if rcv := recover(); rcv != nil {
			w.Header().Set(tagX_edo_cooperation_error, fmt.Sprint(rcv))
			idperr.RespondJson(w, r, erro.New(rcv), logPref)
			return
		}
	}()

	if this.stopper != nil {
		this.stopper.Stop()
		defer this.stopper.Unstop()
	}

	logPref = server.ParseSender(r) + ": "

	server.LogRequest(level.DEBUG, r, this.debug, logPref)

	log.Info(logPref, "Received cooperation request")
	defer log.Info(logPref, "Handled cooperation request")

	if err := (&environment{this, logPref}).serve(w, r); err != nil {
		w.Header().Set(tagX_edo_cooperation_error, idperr.From(err).ErrorDescription())
		idperr.RespondJson(w, r, erro.Wrap(err), logPref)
		return
	}
}
コード例 #15
0
ファイル: main_test.go プロジェクト: realglobe-Inc/edo-auth
func setupIdpDb(db, coll string, idps []idpdb.Element) error {
	conn := monPool.New()
	defer conn.Close()

	for _, idp := range idps {
		keys := []map[string]interface{}{}
		for _, key := range idp.Keys() {
			keys = append(keys, key.ToMap())
		}
		m := bson.M{
			"issuer":                    idp.Id(),
			"authorization_endpoint":    idp.AuthUri(),
			"token_endpoint":            idp.TokenUri(),
			"userinfo_endpoint":         idp.AccountUri(),
			"cooperation_from_endpoint": idp.CoopFromUri(),
			"cooperation_to_endpoint":   idp.CoopToUri(),
			"jwks": keys,
		}
		for k, v := range idp.Names() {
			if k == "" {
				m["issuer_name"] = v
			} else {
				m["issuer_name#"+k] = v
			}
		}
		if err := conn.DB(db).C(coll).Insert(m); err != nil {
			return erro.Wrap(err)
		}
	}
	return nil
}
コード例 #16
0
ファイル: rotate.go プロジェクト: realglobe-Inc/go-lib
func (buff *fileLogBuffer) flush() error {
	n := 0
	writeBuff := []byte{}
	for elem := buff.unwritten.Front(); elem != nil; elem = elem.Next() {
		log := elem.Value.([]byte)
		if curSize := buff.sinkSize + len(writeBuff); curSize > 0 && // サイズオーバーしても 1 個は必ず書く。
			curSize+len(log) > buff.limit {
			break
		}
		writeBuff = append(writeBuff, log...)
		n++
	}

	if _, err := buff.sink.Write(writeBuff); err != nil {
		return erro.Wrap(err)
	}

	buff.sinkSize += len(writeBuff)
	if n == buff.unwritten.Len() {
		// 全部書き出した。
		buff.unwritten.Init()
		buff.unwrittenSize = 0
		return nil
	}

	// n 個だけ書き出した。

	for i := 0; i < n; i++ {
		buff.unwritten.Remove(buff.unwritten.Front())
	}
	buff.unwrittenSize -= len(writeBuff)
	return fileIsFull
}
コード例 #17
0
func (this *Page) HandleCallback(w http.ResponseWriter, r *http.Request) {
	var logPref string

	// panic 対策。
	defer func() {
		if rcv := recover(); rcv != nil {
			server.RespondErrorHtml(w, r, erro.New(rcv), this.errTmpl, logPref)
			return
		}
	}()

	if this.stopper != nil {
		this.stopper.Stop()
		defer this.stopper.Unstop()
	}

	sender := request.Parse(r, this.sessLabel)
	logPref = sender.String() + ": "

	server.LogRequest(level.DEBUG, r, this.debug, logPref)

	log.Info(logPref, "Received callback request")
	defer log.Info(logPref, "Handled callback request")

	if err := (&environment{this, logPref, sender.Session(), nil}).callbackServe(w, r); err != nil {
		server.RespondErrorHtml(w, r, erro.Wrap(err), this.errTmpl, logPref)
		return
	}
	return
}
コード例 #18
0
func newTestIdProvider(keys []jwk.Key) (*testIdProvider, error) {
	base, err := test.NewHttpServer(time.Minute)
	if err != nil {
		return nil, erro.Wrap(err)
	}
	return &testIdProvider{base, keys}, nil
}
コード例 #19
0
// ユーザー認証開始。
func (this *Page) HandleAuth(w http.ResponseWriter, r *http.Request) {
	var logPref string

	// panic 対策。
	defer func() {
		if rcv := recover(); rcv != nil {
			server.RespondErrorHtml(w, r, erro.New(rcv), this.errTmpl, logPref)
			return
		}
	}()

	if this.stopper != nil {
		this.stopper.Stop()
		defer this.stopper.Unstop()
	}

	logPref = server.ParseSender(r) + ": "

	server.LogRequest(level.DEBUG, r, this.debug, logPref)

	log.Info(logPref, "Received authentication request")
	defer log.Info(logPref, "Handled authentication request")

	if err := (&environment{this, logPref, "", nil}).authServe(w, r); err != nil {
		server.RespondErrorHtml(w, r, erro.Wrap(err), this.errTmpl, logPref)
		return
	}
	return
}
コード例 #20
0
ファイル: element.go プロジェクト: realglobe-Inc/edo-auth
func (this *Element) UnmarshalJSON(data []byte) error {
	var buff struct {
		Id      string    `json:"id"`
		Inv     bool      `json:"invalid"`
		Exp     time.Time `json:"expires"`
		Path    string    `json:"path"`
		Idp     string    `json:"id_provider"`
		Ta      string    `json:"client_id"`
		RediUri string    `json:"redirect_uri"`
		Stat    string    `json:"state"`
		Nonc    string    `json:"nonce"`
		Date    time.Time `json:"date"`
	}
	if err := json.Unmarshal(data, &buff); err != nil {
		return erro.Wrap(err)
	}

	this.id = buff.Id
	this.inv = buff.Inv
	this.exp = buff.Exp
	this.path = buff.Path
	this.idp = buff.Idp
	this.ta = buff.Ta
	this.rediUri = buff.RediUri
	this.stat = buff.Stat
	this.nonc = buff.Nonc
	this.date = buff.Date
	return nil
}
コード例 #21
0
func parseTokenResponse(resp *http.Response) (*tokenResponse, error) {
	var buff struct {
		Access_token string
		Expires_in   int
		Scope        string
		Id_token     string
	}
	if err := json.NewDecoder(resp.Body).Decode(&buff); err != nil {
		return nil, erro.Wrap(err)
	} else if buff.Access_token == "" {
		return nil, erro.New("no access token")
	}

	var exp time.Time
	if buff.Expires_in != 0 {
		exp = time.Now().Add(time.Duration(buff.Expires_in) * time.Second)
	}
	var scop map[string]bool
	if buff.Scope != "" {
		scop = request.FormValueSet(buff.Scope)
	}
	var idTok []byte
	if buff.Id_token != "" {
		idTok = []byte(buff.Id_token)
	}

	return &tokenResponse{
		tok:   buff.Access_token,
		exp:   exp,
		scop:  scop,
		idTok: idTok,
	}, nil
}
コード例 #22
0
ファイル: syslog.go プロジェクト: realglobe-Inc/go-lib
func (core *syslogCoreHandler) close() {
	core.flush()

	if err := core.base.Close(); err != nil {
		err = erro.Wrap(err)
		fmt.Fprintln(os.Stderr, err)
	}
}
コード例 #23
0
ファイル: values_test.go プロジェクト: realglobe-Inc/edo-auth
func newAuthRequest() (*http.Request, error) {
	r, err := http.NewRequest("GET", "http://localhost/", nil)
	if err != nil {
		return nil, erro.Wrap(err)
	}
	r.Header.Set("X-Auth-Uri", test_idp.AuthUri())
	return r, nil
}
コード例 #24
0
ファイル: level.go プロジェクト: realglobe-Inc/go-lib
func (v levelVar) Set(s string) error {
	var err error
	*v.Level, err = ValueOf(s)
	if err != nil {
		return erro.Wrap(err)
	}
	return nil
}
コード例 #25
0
ファイル: id_token.go プロジェクト: realglobe-Inc/edo-auth
func parseIdToken(raw []byte) (*idToken, error) {
	base, err := jwt.Parse(raw)
	if err != nil {
		return nil, erro.Wrap(err)
	}
	alg, _ := base.Header(tagAlg).(string)
	if alg == "" {
		return nil, erro.New("no alg")
	}
	var buff struct {
		Idp    string `json:"iss"`
		Nonc   string `json:"nonce"`
		CHash  string `json:"c_hash"`
		AtHash string `json:"at_hash"`
	}
	if err := json.Unmarshal(base.RawBody(), &buff); err != nil {
		return nil, erro.Wrap(err)
	} else if buff.Idp == "" {
		return nil, erro.New("no ID provider ID")
	} else if buff.Nonc == "" {
		return nil, erro.New("no nonce")
	}
	var cHash, atHash []byte
	if buff.CHash != "" {
		cHash, err = base64.RawURLEncoding.DecodeString(buff.CHash)
		if err != nil {
			return nil, erro.Wrap(err)
		}
	}
	if buff.AtHash != "" {
		atHash, err = base64.RawURLEncoding.DecodeString(buff.AtHash)
		if err != nil {
			return nil, erro.Wrap(err)
		}
	}

	return &idToken{
		base:   base,
		alg:    alg,
		idp:    buff.Idp,
		nonc:   buff.Nonc,
		cHash:  cHash,
		atHash: atHash,
	}, nil
}
コード例 #26
0
ファイル: values_test.go プロジェクト: realglobe-Inc/edo-auth
func newAuthRequest(uri, idpUri string) (*http.Request, error) {
	r, err := http.NewRequest("GET", uri, nil)
	if err != nil {
		return nil, erro.Wrap(err)
	}
	r.Header.Set("X-Auth-Uri", idpUri)
	r.Header.Set("Connection", "close")
	return r, nil
}
コード例 #27
0
ファイル: simple.go プロジェクト: realglobe-Inc/go-lib
func (hndl *flushHandler) Flush() {
	hndl.lock.Lock()
	defer hndl.lock.Unlock()

	if err := hndl.flusher.Flush(); err != nil {
		err = erro.Wrap(err)
		fmt.Fprintln(os.Stderr, err)
	}
}
コード例 #28
0
ファイル: rotate.go プロジェクト: realglobe-Inc/go-lib
func (buff *fileLogBuffer) setSink(sink *os.File) error {
	stat, err := sink.Stat()
	if err != nil {
		return erro.Wrap(err)
	}
	buff.sink = sink
	buff.sinkSize = int(stat.Size())
	return nil
}
コード例 #29
0
ファイル: lock_linux.go プロジェクト: realglobe-Inc/go-lib
func lock(path string, flag int) (*Locker, error) {
	file, err := os.Create(path)
	if err != nil {
		return nil, erro.Wrap(err)
	}

	if err := syscall.Flock(int(file.Fd()), syscall.LOCK_EX|flag); err != nil {
		file.Close()

		if err == syscall.EWOULDBLOCK {
			// ロックできなかった。
			return nil, nil
		}

		return nil, erro.Wrap(err)
	}

	return (*Locker)(file), nil
}
コード例 #30
0
func (this *redisDb) Save(elem *Element, exp time.Time) error {
	conn := this.pool.Get()
	defer conn.Close()

	data, err := json.Marshal(elem)
	if err != nil {
		return erro.Wrap(err)
	}
	expIn := int64(exp.Sub(time.Now()) / time.Millisecond)

	conn.Send("MULTI")
	conn.Send("SET", this.tag+elem.Id(), data, "PX", expIn)
	conn.Send("SET", this.tag+tagDate+elem.Id(), elem.Date().UnixNano(), "PX", expIn)
	if _, err := conn.Do("EXEC"); err != nil {
		return erro.Wrap(err)
	}

	return nil
}