<commit_before>package slinga

import (
	"bytes"
	"errors"
	"fmt"
	"strings"
	"text/template"
)

type templateData struct {
	Labels    map[string]string
	User      *User
	Discovery NestedParameterMap
}

// Evaluates a template
func evaluateTemplate(templateStr string, user *User, labels LabelSet) (string, error) {
	type Parameters struct {
		User   *User
		Labels map[string]string
	}
	param := Parameters{User: user, Labels: labels.Labels}

	tmpl, err := template.New("").Parse(templateStr)
	if err != nil {
		return "", fmt.Errorf("Invalid template %s: %s", templateStr, err.Error())
	}

	var doc bytes.Buffer
	err = tmpl.Execute(&doc, param)

	if err != nil {
		return "", fmt.Errorf("Cannot evaluate template %s: %s", templateStr, err.Error())
	}

	result := doc.String()
	if strings.Contains(result, "<no value>") {
		return "", fmt.Errorf("Cannot evaluate template %s: <no value>", templateStr)
	}

	return doc.String(), nil
}

func (component *ServiceComponent) processTemplateParams(template interface{}, componentKey string, labels LabelSet, user *User, discoveryTree NestedParameterMap, templateType string, depth int) (NestedParameterMap, error) {
	if template == nil {
		return nil, nil
	}
	tracing.Printf(depth+1, "Component: %s (%s)", component.Name, templateType)

	// Create a copy of discovery tree, so we can add our own instance into it
	discoveryTreeCopy := discoveryTree.makeCopy()
	discoveryTreeCopy["instance"] = EscapeName(componentKey)

	templateData := templateData{
		Labels:    labels.Labels,
		Discovery: discoveryTreeCopy,
		User:      user}

	var evalParamsInterface func(params interface{}) (interface{}, error)

	// TODO: this method needs to be fixed to use less interface{} :-)
	evalParamsInterface = func(params interface{}) (interface{}, error) {
		if params == nil {
			return "", nil
		} else if paramsMap, ok := params.(map[interface{}]interface{}); ok {
			resultMap := make(map[interface{}]interface{})

			for key, value := range paramsMap {
				evaluatedValue, err := evalParamsInterface(value)
				if err != nil {
					return nil, err
				}
				resultMap[key] = evaluatedValue
			}

			return resultMap, nil
		} else if paramsStr, ok := params.(string); ok {
			evaluatedValue, err := evaluateCodeParamTemplate(paramsStr, templateData)
			tracing.Printf(depth+2, "Parameter '%s': %s", paramsStr, evaluatedValue)
			if err != nil {
				return nil, err
			}
			return evaluatedValue, nil
		} else if paramsInt, ok := params.(int); ok {
			return paramsInt, nil
		} else if paramsBool, ok := params.(bool); ok {
			return paramsBool, nil
		}

		return nil, errors.New("There should be map[string]interface{} or string")
	}

	resultMap, err := evalParamsInterface(template)
	if err != nil {
		return nil, err
	}

	result := NestedParameterMap{}
	for k, v := range resultMap.(map[interface{}]interface{}) {
		result[k.(string)] = v
	}
	return result, err
}

func evaluateCodeParamTemplate(templateStr string, templateData templateData) (string, error) {
	tmpl, err := template.New("").Parse(templateStr)
	if err != nil {
		return "", errors.New("Invalid template " + templateStr)
	}

	var doc bytes.Buffer
	err = tmpl.Execute(&doc, templateData)

	if err != nil {
		return "", errors.New("Cannot evaluate template " + templateStr)
	}

	result := doc.String()
	if strings.Contains(result, "<no value>") {
		return "", errors.New("Cannot evaluate template " + templateStr)
	}

	return EscapeName(doc.String()), nil
}
<commit_msg>make validate fixed<commit_after>package slinga

import (
	"bytes"
	"errors"
	"fmt"
	"strings"
	"text/template"
)

type templateData struct {
	Labels    map[string]string
	User      *User
	Discovery NestedParameterMap
}

// Evaluates a template
func evaluateTemplate(templateStr string, user *User, labels LabelSet) (string, error) {
	type Parameters struct {
		User   *User
		Labels map[string]string
	}
	param := Parameters{User: user, Labels: labels.Labels}

	tmpl, err := template.New("").Parse(templateStr)
	if err != nil {
		return "", fmt.Errorf("Invalid template %s: %s", templateStr, err.Error())
	}

	var doc bytes.Buffer
	err = tmpl.Execute(&doc, param)

	if err != nil {
		return "", fmt.Errorf("Cannot evaluate template %s: %s", templateStr, err.Error())
	}

	result := doc.String()
	if strings.Contains(result, "<no value>") {
		return "", fmt.Errorf("Cannot evaluate template %s: <no value>", templateStr)
	}

	return doc.String(), nil
}

func (component *ServiceComponent) processTemplateParams(template interface{}, componentKey string, labels LabelSet, user *User, discoveryTree NestedParameterMap, templateType string, depth int) (NestedParameterMap, error) {
	if template == nil {
		return nil, nil
	}
	tracing.Printf(depth+1, "Component: %s (%s)", component.Name, templateType)

	// Create a copy of discovery tree, so we can add our own instance into it
	discoveryTreeCopy := discoveryTree.makeCopy()
	discoveryTreeCopy["instance"] = EscapeName(componentKey)

	tData := templateData{
		Labels:    labels.Labels,
		Discovery: discoveryTreeCopy,
		User:      user}

	var evalParamsInterface func(params interface{}) (interface{}, error)

	// TODO: this method needs to be fixed to use less interface{} :-)
	evalParamsInterface = func(params interface{}) (interface{}, error) {
		if params == nil {
			return "", nil
		} else if paramsMap, ok := params.(map[interface{}]interface{}); ok {
			resultMap := make(map[interface{}]interface{})

			for key, value := range paramsMap {
				evaluatedValue, err := evalParamsInterface(value)
				if err != nil {
					return nil, err
				}
				resultMap[key] = evaluatedValue
			}

			return resultMap, nil
		} else if paramsStr, ok := params.(string); ok {
			evaluatedValue, err := evaluateCodeParamTemplate(paramsStr, tData)
			tracing.Printf(depth+2, "Parameter '%s': %s", paramsStr, evaluatedValue)
			if err != nil {
				return nil, err
			}
			return evaluatedValue, nil
		} else if paramsInt, ok := params.(int); ok {
			return paramsInt, nil
		} else if paramsBool, ok := params.(bool); ok {
			return paramsBool, nil
		}

		return nil, errors.New("There should be map[string]interface{} or string")
	}

	resultMap, err := evalParamsInterface(template)
	if err != nil {
		return nil, err
	}

	result := NestedParameterMap{}
	for k, v := range resultMap.(map[interface{}]interface{}) {
		result[k.(string)] = v
	}
	return result, err
}

func evaluateCodeParamTemplate(templateStr string, tData templateData) (string, error) {
	tmpl, err := template.New("").Parse(templateStr)
	if err != nil {
		return "", errors.New("Invalid template " + templateStr)
	}

	var doc bytes.Buffer
	err = tmpl.Execute(&doc, tData)

	if err != nil {
		return "", errors.New("Cannot evaluate template " + templateStr)
	}

	result := doc.String()
	if strings.Contains(result, "<no value>") {
		return "", errors.New("Cannot evaluate template " + templateStr)
	}

	return EscapeName(doc.String()), nil
}
<|endoftext|>


<commit_before>// Copyright 2019 Istio Authors
//
// 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 label

const (
	// Presubmit indicates that the test should be run as part of a presubmit run.
	Presubmit Instance = "presubmit"

	// Postsubmit indicates that the test should be run as part of a postsubmit run.
	Postsubmit Instance = "postsubmit"

	// CustomSetup indicates that the test requires a custom Istio installation.
	CustomSetup Instance = "customsetup"
)

var all = NewSet(
	Presubmit,
	Postsubmit,
	CustomSetup)
<commit_msg>[Testing] Add Flaky label. (#13796)<commit_after>// Copyright 2019 Istio Authors
//
// 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 label

const (
	// Presubmit indicates that the test should be run as part of a presubmit run.
	Presubmit Instance = "presubmit"

	// Postsubmit indicates that the test should be run as part of a postsubmit run.
	Postsubmit Instance = "postsubmit"

	// CustomSetup indicates that the test requires a custom Istio installation.
	CustomSetup Instance = "customsetup"

	// Flaky indicates that a test is currently flaky and should not be run as part
	// of presubmit or postsubmit. When a test is determined to be Flaky, a github
	// issue should be created to fix the test.
	Flaky Instance = "flaky"
)

var all = NewSet(
	Presubmit,
	Postsubmit,
	CustomSetup,
	Flaky)
<|endoftext|>


<commit_before>/*
Copyright 2014 The Camlistore Authors.

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 integration

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"camlistore.org/pkg/test"
)

func TestFileSharing(t *testing.T) {
	share(t, "share_test.go")
}

func TestDirSharing(t *testing.T) {
	share(t, filepath.FromSlash("../integration"))
}

func share(t *testing.T, file string) {
	w := test.GetWorld(t)
	out := test.MustRunCmd(t, w.Cmd("camput", "file", file))
	fileRef := strings.Split(out, "\n")[0]

	out = test.MustRunCmd(t, w.Cmd("camput", "share", "-transitive", fileRef))
	shareRef := strings.Split(out, "\n")[0]

	testDir, err := ioutil.TempDir("", "camli-share-test-")
	if err != nil {
		t.Fatalf("ioutil.TempDir(): %v", err)
	}
	defer os.RemoveAll(testDir)

	// test that we can get it through the share
	test.MustRunCmd(t, w.Cmd("camget", "-o", testDir, "-shared", fmt.Sprintf("%v/share/%v", w.ServerBaseURL(), shareRef)))
	if _, err := os.Stat(filepath.Join(testDir, filepath.Base(file))); err != nil {
		t.Fatalf("camget -shared failed to get %v: %v", file, err)
	}

	// test that we're not allowed to get it directly
	fileURL := fmt.Sprintf("%v/share/%v", w.ServerBaseURL(), fileRef)
	_, err = test.RunCmd(w.Cmd("camget", "-shared", fileURL))
	if err == nil {
		t.Fatal("Was expecting error for 'camget -shared " + fileURL + "'")
	}
	if !strings.Contains(err.Error(), "client: got status code 401") {
		t.Fatalf("'camget -shared %v': got error %v, was expecting 401", fileURL, err)
	}
}
<commit_msg>integration/sharing: test that we also camget the dir contents<commit_after>/*
Copyright 2014 The Camlistore Authors.

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 integration

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"camlistore.org/pkg/test"
)

func TestFileSharing(t *testing.T) {
	share(t, "share_test.go")
}

func TestDirSharing(t *testing.T) {
	share(t, filepath.FromSlash("../integration"))
}

func share(t *testing.T, file string) {
	w := test.GetWorld(t)
	out := test.MustRunCmd(t, w.Cmd("camput", "file", file))
	fileRef := strings.Split(out, "\n")[0]

	out = test.MustRunCmd(t, w.Cmd("camput", "share", "-transitive", fileRef))
	shareRef := strings.Split(out, "\n")[0]

	testDir, err := ioutil.TempDir("", "camli-share-test-")
	if err != nil {
		t.Fatalf("ioutil.TempDir(): %v", err)
	}
	defer os.RemoveAll(testDir)

	// test that we can get it through the share
	test.MustRunCmd(t, w.Cmd("camget", "-o", testDir, "-shared", fmt.Sprintf("%v/share/%v", w.ServerBaseURL(), shareRef)))
	filePath := filepath.Join(testDir, filepath.Base(file))
	fi, err := os.Stat(filePath)
	if err != nil {
		t.Fatalf("camget -shared failed to get %v: %v", file, err)
	}
	if fi.IsDir() {
		// test that we also get the dir contents
		d, err := os.Open(filePath)
		if err != nil {
			t.Fatal(err)
		}
		defer d.Close()
		names, err := d.Readdirnames(-1)
		if err != nil {
			t.Fatal(err)
		}
		if len(names) == 0 {
			t.Fatalf("camget did not fetch contents of directory %v", file)
		}
	}

	// test that we're not allowed to get it directly
	fileURL := fmt.Sprintf("%v/share/%v", w.ServerBaseURL(), fileRef)
	_, err = test.RunCmd(w.Cmd("camget", "-shared", fileURL))
	if err == nil {
		t.Fatal("Was expecting error for 'camget -shared " + fileURL + "'")
	}
	if !strings.Contains(err.Error(), "client: got status code 401") {
		t.Fatalf("'camget -shared %v': got error %v, was expecting 401", fileURL, err)
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"encoding/base64"
	"time"

	"github.com/fatih/structs"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

func pathBlacklistRoleTag(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "blacklist/roletag/(?P<role_tag>.*)",
		Fields: map[string]*framework.FieldSchema{
			"role_tag": &framework.FieldSchema{
				Type: framework.TypeString,
				Description: `Role tag to be blacklisted. The tag can be supplied as-is. In order
to avoid any encoding problems, it can be base64 encoded.`,
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathBlacklistRoleTagUpdate,
			logical.ReadOperation:   b.pathBlacklistRoleTagRead,
			logical.DeleteOperation: b.pathBlacklistRoleTagDelete,
		},

		HelpSynopsis:    pathBlacklistRoleTagSyn,
		HelpDescription: pathBlacklistRoleTagDesc,
	}
}

// Path to list all the blacklisted tags.
func pathListBlacklistRoleTags(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "blacklist/roletags/?",

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.ListOperation: b.pathBlacklistRoleTagsList,
		},

		HelpSynopsis:    pathListBlacklistRoleTagsHelpSyn,
		HelpDescription: pathListBlacklistRoleTagsHelpDesc,
	}
}

// Lists all the blacklisted role tags.
func (b *backend) pathBlacklistRoleTagsList(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	tags, err := req.Storage.List("blacklist/roletag/")
	if err != nil {
		return nil, err
	}

	// Tags are base64 encoded before indexing to avoid problems
	// with the path separators being present in the tag.
	// Reverse it before returning the list response.
	for i, keyB64 := range tags {
		if key, err := base64.StdEncoding.DecodeString(keyB64); err != nil {
			return nil, err
		} else {
			// Overwrite the result with the decoded string.
			tags[i] = string(key)
		}
	}
	return logical.ListResponse(tags), nil
}

// Fetch an entry from the role tag blacklist for a given tag.
// This method takes a role tag in its original form and not a base64 encoded form.
func blacklistRoleTagEntry(s logical.Storage, tag string) (*roleTagBlacklistEntry, error) {
	entry, err := s.Get("blacklist/roletag/" + base64.StdEncoding.EncodeToString([]byte(tag)))
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return nil, nil
	}

	var result roleTagBlacklistEntry
	if err := entry.DecodeJSON(&result); err != nil {
		return nil, err
	}
	return &result, nil
}

// Deletes an entry from the role tag blacklist for a given tag.
func (b *backend) pathBlacklistRoleTagDelete(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	tag := data.Get("role_tag").(string)
	if tag == "" {
		return logical.ErrorResponse("missing role_tag"), nil
	}

	return nil, req.Storage.Delete("blacklist/roletag/" + base64.StdEncoding.EncodeToString([]byte(tag)))
}

// If the given role tag is blacklisted, returns the details of the blacklist entry.
// Returns 'nil' otherwise.
func (b *backend) pathBlacklistRoleTagRead(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {

	tag := data.Get("role_tag").(string)
	if tag == "" {
		return logical.ErrorResponse("missing role_tag"), nil
	}

	entry, err := blacklistRoleTagEntry(req.Storage, tag)
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return nil, nil
	}

	return &logical.Response{
		Data: structs.New(entry).Map(),
	}, nil
}

// pathBlacklistRoleTagUpdate is used to blacklist a given role tag.
// Before a role tag is blacklisted, the correctness of the plaintext part
// in the role tag is verified using the associated HMAC.
func (b *backend) pathBlacklistRoleTagUpdate(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {

	// The role_tag value provided, optionally can be base64 encoded.
	tagInput := data.Get("role_tag").(string)
	if tagInput == "" {
		return logical.ErrorResponse("missing role_tag"), nil
	}

	tag := ""

	// Try to base64 decode the value.
	tagBytes, err := base64.StdEncoding.DecodeString(tagInput)
	if err != nil {
		// If the decoding failed, use the value as-is.
		tag = tagInput
	} else {
		// If the decoding succeeded, use the decoded value.
		tag = string(tagBytes)
	}

	// Parse and the role tag from string form to a struct form and verify it.
	rTag, err := parseAndVerifyRoleTagValue(req.Storage, tag)
	if err != nil {
		return nil, err
	}
	if rTag == nil {
		return logical.ErrorResponse("failed to verify the role tag and parse it"), nil
	}

	// Get the entry for the role mentioned in the role tag.
	roleEntry, err := awsRole(req.Storage, rTag.RoleName)
	if err != nil {
		return nil, err
	}
	if roleEntry == nil {
		return logical.ErrorResponse("role entry not found"), nil
	}

	// Check if the role tag is already blacklisted. If yes, update it.
	blEntry, err := blacklistRoleTagEntry(req.Storage, tag)
	if err != nil {
		return nil, err
	}
	if blEntry == nil {
		blEntry = &roleTagBlacklistEntry{}
	}

	currentTime := time.Now().UTC()

	// Check if this is a creation of blacklist entry.
	if blEntry.CreationTime.IsZero() {
		// Set the creation time for the blacklist entry.
		// This should not be updated after setting it once.
		// If blacklist operation is invoked more than once, only update the expiration time.
		blEntry.CreationTime = currentTime
	}

	// Decide the expiration time based on the max_ttl values.

	// If max_ttl is not set for the role tag, fall back on the mount's max_ttl.
	if rTag.MaxTTL == time.Duration(0) {
		rTag.MaxTTL = b.System().MaxLeaseTTL()
	}

	// The max_ttl value on the role tag is scoped by the value set on the role entry.
	if roleEntry.MaxTTL > time.Duration(0) && rTag.MaxTTL > roleEntry.MaxTTL {
		rTag.MaxTTL = roleEntry.MaxTTL
	}

	// Expiration time is decided by least of the max_ttl values set on:
	// role tag, role entry, backend's mount.
	blEntry.ExpirationTime = currentTime.Add(rTag.MaxTTL)

	entry, err := logical.StorageEntryJSON("blacklist/roletag/"+base64.StdEncoding.EncodeToString([]byte(tag)), blEntry)
	if err != nil {
		return nil, err
	}

	// Store the blacklist entry.
	if err := req.Storage.Put(entry); err != nil {
		return nil, err
	}

	return nil, nil
}

type roleTagBlacklistEntry struct {
	CreationTime   time.Time `json:"creation_time" structs:"creation_time" mapstructure:"creation_time"`
	ExpirationTime time.Time `json:"expiration_time" structs:"expiration_time" mapstructure:"expiration_time"`
}

const pathBlacklistRoleTagSyn = `
Blacklist a previously created role tag.
`

const pathBlacklistRoleTagDesc = `
Blacklist a role tag so that it cannot be used by any EC2 instance to perform logins
in the future. This can be used if the role tag is suspected or believed to be possessed
by an unintended party.

By default, a cron task will periodically looks for expired entries in the blacklist
and delete them. The duration to periodically run this, is one hour by default.
However, this can be configured using the 'config/tidy/roletags' endpoint. This tidy
action can be triggered via the API as well, using the 'tidy/roletags' endpoint.

Also note that delete operation is supported on this endpoint to remove specific
entries from the blacklist.
`

const pathListBlacklistRoleTagsHelpSyn = `
List the blacklisted role tags.
`

const pathListBlacklistRoleTagsHelpDesc = `
List all the entries present in the blacklist. This will show both the valid
entries and the expired entries in the blacklist. Use 'tidy/roletags' endpoint
to clean-up the blacklist of role tags based on expiration time.
`
<commit_msg>Make the roletag blacklist the longest duration, not least<commit_after>package aws

import (
	"encoding/base64"
	"time"

	"github.com/fatih/structs"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

func pathBlacklistRoleTag(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "blacklist/roletag/(?P<role_tag>.*)",
		Fields: map[string]*framework.FieldSchema{
			"role_tag": &framework.FieldSchema{
				Type: framework.TypeString,
				Description: `Role tag to be blacklisted. The tag can be supplied as-is. In order
to avoid any encoding problems, it can be base64 encoded.`,
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathBlacklistRoleTagUpdate,
			logical.ReadOperation:   b.pathBlacklistRoleTagRead,
			logical.DeleteOperation: b.pathBlacklistRoleTagDelete,
		},

		HelpSynopsis:    pathBlacklistRoleTagSyn,
		HelpDescription: pathBlacklistRoleTagDesc,
	}
}

// Path to list all the blacklisted tags.
func pathListBlacklistRoleTags(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "blacklist/roletags/?",

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.ListOperation: b.pathBlacklistRoleTagsList,
		},

		HelpSynopsis:    pathListBlacklistRoleTagsHelpSyn,
		HelpDescription: pathListBlacklistRoleTagsHelpDesc,
	}
}

// Lists all the blacklisted role tags.
func (b *backend) pathBlacklistRoleTagsList(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	tags, err := req.Storage.List("blacklist/roletag/")
	if err != nil {
		return nil, err
	}

	// Tags are base64 encoded before indexing to avoid problems
	// with the path separators being present in the tag.
	// Reverse it before returning the list response.
	for i, keyB64 := range tags {
		if key, err := base64.StdEncoding.DecodeString(keyB64); err != nil {
			return nil, err
		} else {
			// Overwrite the result with the decoded string.
			tags[i] = string(key)
		}
	}
	return logical.ListResponse(tags), nil
}

// Fetch an entry from the role tag blacklist for a given tag.
// This method takes a role tag in its original form and not a base64 encoded form.
func blacklistRoleTagEntry(s logical.Storage, tag string) (*roleTagBlacklistEntry, error) {
	entry, err := s.Get("blacklist/roletag/" + base64.StdEncoding.EncodeToString([]byte(tag)))
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return nil, nil
	}

	var result roleTagBlacklistEntry
	if err := entry.DecodeJSON(&result); err != nil {
		return nil, err
	}
	return &result, nil
}

// Deletes an entry from the role tag blacklist for a given tag.
func (b *backend) pathBlacklistRoleTagDelete(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	tag := data.Get("role_tag").(string)
	if tag == "" {
		return logical.ErrorResponse("missing role_tag"), nil
	}

	return nil, req.Storage.Delete("blacklist/roletag/" + base64.StdEncoding.EncodeToString([]byte(tag)))
}

// If the given role tag is blacklisted, returns the details of the blacklist entry.
// Returns 'nil' otherwise.
func (b *backend) pathBlacklistRoleTagRead(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {

	tag := data.Get("role_tag").(string)
	if tag == "" {
		return logical.ErrorResponse("missing role_tag"), nil
	}

	entry, err := blacklistRoleTagEntry(req.Storage, tag)
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return nil, nil
	}

	return &logical.Response{
		Data: structs.New(entry).Map(),
	}, nil
}

// pathBlacklistRoleTagUpdate is used to blacklist a given role tag.
// Before a role tag is blacklisted, the correctness of the plaintext part
// in the role tag is verified using the associated HMAC.
func (b *backend) pathBlacklistRoleTagUpdate(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {

	// The role_tag value provided, optionally can be base64 encoded.
	tagInput := data.Get("role_tag").(string)
	if tagInput == "" {
		return logical.ErrorResponse("missing role_tag"), nil
	}

	tag := ""

	// Try to base64 decode the value.
	tagBytes, err := base64.StdEncoding.DecodeString(tagInput)
	if err != nil {
		// If the decoding failed, use the value as-is.
		tag = tagInput
	} else {
		// If the decoding succeeded, use the decoded value.
		tag = string(tagBytes)
	}

	// Parse and verify the role tag from string form to a struct form and verify it.
	rTag, err := parseAndVerifyRoleTagValue(req.Storage, tag)
	if err != nil {
		return nil, err
	}
	if rTag == nil {
		return logical.ErrorResponse("failed to verify the role tag and parse it"), nil
	}

	// Get the entry for the role mentioned in the role tag.
	roleEntry, err := awsRole(req.Storage, rTag.RoleName)
	if err != nil {
		return nil, err
	}
	if roleEntry == nil {
		return logical.ErrorResponse("role entry not found"), nil
	}

	// Check if the role tag is already blacklisted. If yes, update it.
	blEntry, err := blacklistRoleTagEntry(req.Storage, tag)
	if err != nil {
		return nil, err
	}
	if blEntry == nil {
		blEntry = &roleTagBlacklistEntry{}
	}

	currentTime := time.Now().UTC()

	// Check if this is a creation of blacklist entry.
	if blEntry.CreationTime.IsZero() {
		// Set the creation time for the blacklist entry.
		// This should not be updated after setting it once.
		// If blacklist operation is invoked more than once, only update the expiration time.
		blEntry.CreationTime = currentTime
	}

	// Decide the expiration time based on the max_ttl values. Since this is
	// restricting access, use the greatest duration, not the least.
	maxDur := rTag.MaxTTL
	if roleEntry.MaxTTL > maxDur {
		maxDur = roleEntry.MaxTTL
	}
	if b.System().MaxLeaseTTL() > maxDur {
		maxDur = b.System().MaxLeaseTTL()
	}

	blEntry.ExpirationTime = currentTime.Add(maxDur)

	entry, err := logical.StorageEntryJSON("blacklist/roletag/"+base64.StdEncoding.EncodeToString([]byte(tag)), blEntry)
	if err != nil {
		return nil, err
	}

	// Store the blacklist entry.
	if err := req.Storage.Put(entry); err != nil {
		return nil, err
	}

	return nil, nil
}

type roleTagBlacklistEntry struct {
	CreationTime   time.Time `json:"creation_time" structs:"creation_time" mapstructure:"creation_time"`
	ExpirationTime time.Time `json:"expiration_time" structs:"expiration_time" mapstructure:"expiration_time"`
}

const pathBlacklistRoleTagSyn = `
Blacklist a previously created role tag.
`

const pathBlacklistRoleTagDesc = `
Blacklist a role tag so that it cannot be used by any EC2 instance to perform logins
in the future. This can be used if the role tag is suspected or believed to be possessed
by an unintended party.

By default, a cron task will periodically looks for expired entries in the blacklist
and delete them. The duration to periodically run this, is one hour by default.
However, this can be configured using the 'config/tidy/roletags' endpoint. This tidy
action can be triggered via the API as well, using the 'tidy/roletags' endpoint.

Also note that delete operation is supported on this endpoint to remove specific
entries from the blacklist.
`

const pathListBlacklistRoleTagsHelpSyn = `
List the blacklisted role tags.
`

const pathListBlacklistRoleTagsHelpDesc = `
List all the entries present in the blacklist. This will show both the valid
entries and the expired entries in the blacklist. Use 'tidy/roletags' endpoint
to clean-up the blacklist of role tags based on expiration time.
`
<|endoftext|>


<commit_before>package integration

import (
	"os"
	"testing"

	"github.com/pkg/errors"

	"google.golang.org/grpc"

	"github.com/havoc-io/mutagen/cmd"
	"github.com/havoc-io/mutagen/pkg/agent"
	"github.com/havoc-io/mutagen/pkg/daemon"
	daemonsvc "github.com/havoc-io/mutagen/pkg/service/daemon"
	promptsvc "github.com/havoc-io/mutagen/pkg/service/prompt"
	sessionsvc "github.com/havoc-io/mutagen/pkg/service/session"
	"github.com/havoc-io/mutagen/pkg/session"

	// Explicitly import packages that need to register protocol handlers.
	_ "github.com/havoc-io/mutagen/pkg/integration/protocols/netpipe"
	_ "github.com/havoc-io/mutagen/pkg/protocols/docker"
	_ "github.com/havoc-io/mutagen/pkg/protocols/local"
	_ "github.com/havoc-io/mutagen/pkg/protocols/ssh"
)

// sessionManager is the session manager for the integration testing daemon. It
// is exposed for integration tests that operate at the API level (as opposed to
// the gRPC or command line level).
var sessionManager *session.Manager

// testMainInternal is the internal testing entry point, needed so that shutdown
// operations can be deferred (since TestMain will invoke os.Exit). It copies
// the mutagen executable to a well-known path, sets up the agent bundle to work
// during testing, sets up a functionally complete daemon instance for testing,
// runs integration tests, and finally tears down all of the aforementioned
// infrastructure.
func testMainInternal(m *testing.M) (int, error) {
	// Override the expected agent bundle location.
	agent.ExpectedBundleLocation = agent.BundleLocationBuildDirectory

	// Acquire the daemon lock and defer its release.
	lock, err := daemon.AcquireLock()
	if err != nil {
		return -1, errors.Wrap(err, "unable to acquire daemon lock")
	}
	defer lock.Unlock()

	// Create a session manager and defer its shutdown. Note that we assign to
	// the global instance here.
	sessionManager, err = session.NewManager()
	if err != nil {
		return -1, errors.Wrap(err, "unable to create session manager")
	}
	defer sessionManager.Shutdown()

	// Create the gRPC server and defer its stoppage. We use a hard stop rather
	// than a graceful stop so that it doesn't hang on open requests.
	server := grpc.NewServer(
		grpc.MaxSendMsgSize(daemon.MaximumIPCMessageSize),
		grpc.MaxRecvMsgSize(daemon.MaximumIPCMessageSize),
	)
	defer server.Stop()

	// Create and register the daemon service and defer its shutdown.
	daemonServer := daemonsvc.NewServer()
	daemonsvc.RegisterDaemonServer(server, daemonServer)
	defer daemonServer.Shutdown()

	// Create and register the prompt service.
	promptsvc.RegisterPromptingServer(server, promptsvc.NewServer())

	// Create and register the session service.
	sessionsvc.RegisterSessionsServer(server, sessionsvc.NewServer(sessionManager))

	// Create the daemon listener and defer its closure.
	listener, err := daemon.NewListener()
	if err != nil {
		return -1, errors.Wrap(err, "unable to create daemon listener")
	}
	defer listener.Close()

	// Serve incoming connections in a separate Goroutine. We don't monitor for
	// errors since there's nothing that we can do about them and because
	// they'll likely show up in the test output anyway.
	go server.Serve(listener)

	// Run tests.
	return m.Run(), nil
}

// TestMain is the entry point for integration tests (overriding the default
// generated entry point).
func TestMain(m *testing.M) {
	// Invoke the internal entry point. If there's an error, print it out before
	// exiting.
	result, err := testMainInternal(m)
	if err != nil {
		cmd.Error(err)
	}

	// Exit with the result.
	os.Exit(result)
}
<commit_msg>Fixed integration tests for IPC relocation.<commit_after>package integration

import (
	"os"
	"testing"

	"github.com/pkg/errors"

	"google.golang.org/grpc"

	"github.com/havoc-io/mutagen/cmd"
	"github.com/havoc-io/mutagen/pkg/agent"
	"github.com/havoc-io/mutagen/pkg/ipc"
	"github.com/havoc-io/mutagen/pkg/daemon"
	daemonsvc "github.com/havoc-io/mutagen/pkg/service/daemon"
	promptsvc "github.com/havoc-io/mutagen/pkg/service/prompt"
	sessionsvc "github.com/havoc-io/mutagen/pkg/service/session"
	"github.com/havoc-io/mutagen/pkg/session"

	// Explicitly import packages that need to register protocol handlers.
	_ "github.com/havoc-io/mutagen/pkg/integration/protocols/netpipe"
	_ "github.com/havoc-io/mutagen/pkg/protocols/docker"
	_ "github.com/havoc-io/mutagen/pkg/protocols/local"
	_ "github.com/havoc-io/mutagen/pkg/protocols/ssh"
)

// sessionManager is the session manager for the integration testing daemon. It
// is exposed for integration tests that operate at the API level (as opposed to
// the gRPC or command line level).
var sessionManager *session.Manager

// testMainInternal is the internal testing entry point, needed so that shutdown
// operations can be deferred (since TestMain will invoke os.Exit). It copies
// the mutagen executable to a well-known path, sets up the agent bundle to work
// during testing, sets up a functionally complete daemon instance for testing,
// runs integration tests, and finally tears down all of the aforementioned
// infrastructure.
func testMainInternal(m *testing.M) (int, error) {
	// Override the expected agent bundle location.
	agent.ExpectedBundleLocation = agent.BundleLocationBuildDirectory

	// Acquire the daemon lock and defer its release.
	lock, err := daemon.AcquireLock()
	if err != nil {
		return -1, errors.Wrap(err, "unable to acquire daemon lock")
	}
	defer lock.Unlock()

	// Create a session manager and defer its shutdown. Note that we assign to
	// the global instance here.
	sessionManager, err = session.NewManager()
	if err != nil {
		return -1, errors.Wrap(err, "unable to create session manager")
	}
	defer sessionManager.Shutdown()

	// Create the gRPC server and defer its stoppage. We use a hard stop rather
	// than a graceful stop so that it doesn't hang on open requests.
	server := grpc.NewServer(
		grpc.MaxSendMsgSize(daemon.MaximumIPCMessageSize),
		grpc.MaxRecvMsgSize(daemon.MaximumIPCMessageSize),
	)
	defer server.Stop()

	// Create and register the daemon service and defer its shutdown.
	daemonServer := daemonsvc.NewServer()
	daemonsvc.RegisterDaemonServer(server, daemonServer)
	defer daemonServer.Shutdown()

	// Create and register the prompt service.
	promptsvc.RegisterPromptingServer(server, promptsvc.NewServer())

	// Create and register the session service.
	sessionsvc.RegisterSessionsServer(server, sessionsvc.NewServer(sessionManager))

	// Compute the path to the daemon IPC endpoint.
	ipcEndpointPath, err := daemon.IPCEndpointPath()
	if err != nil {
		return -1, errors.Wrap(err, "unable to compute IPC endpoint path")
	}

	// Create the daemon listener and defer its closure.
	listener, err := ipc.NewListener(ipcEndpointPath)
	if err != nil {
		return -1, errors.Wrap(err, "unable to create daemon listener")
	}
	defer listener.Close()

	// Serve incoming connections in a separate Goroutine. We don't monitor for
	// errors since there's nothing that we can do about them and because
	// they'll likely show up in the test output anyway.
	go server.Serve(listener)

	// Run tests.
	return m.Run(), nil
}

// TestMain is the entry point for integration tests (overriding the default
// generated entry point).
func TestMain(m *testing.M) {
	// Invoke the internal entry point. If there's an error, print it out before
	// exiting.
	result, err := testMainInternal(m)
	if err != nil {
		cmd.Error(err)
	}

	// Exit with the result.
	os.Exit(result)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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 apiservice

import (
	"fmt"

	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/validation/field"
	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
	"k8s.io/apiserver/pkg/registry/generic"
	"k8s.io/apiserver/pkg/storage"
	"k8s.io/apiserver/pkg/storage/names"

	"k8s.io/kube-aggregator/pkg/apis/apiregistration"
	"k8s.io/kube-aggregator/pkg/apis/apiregistration/validation"
)

type apiServerStrategy struct {
	runtime.ObjectTyper
	names.NameGenerator
}

func NewStrategy(typer runtime.ObjectTyper) apiServerStrategy {
	return apiServerStrategy{typer, names.SimpleNameGenerator}
}

func (apiServerStrategy) NamespaceScoped() bool {
	return false
}

func (apiServerStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
	apiservice := obj.(*apiregistration.APIService)
	apiservice.Status = apiregistration.APIServiceStatus{}
}

func (apiServerStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
	newAPIService := obj.(*apiregistration.APIService)
	oldAPIService := old.(*apiregistration.APIService)
	newAPIService.Status = oldAPIService.Status
}

func (apiServerStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
	return validation.ValidateAPIService(obj.(*apiregistration.APIService))
}

func (apiServerStrategy) AllowCreateOnUpdate() bool {
	return false
}

func (apiServerStrategy) AllowUnconditionalUpdate() bool {
	return false
}

func (apiServerStrategy) Canonicalize(obj runtime.Object) {
}

func (apiServerStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
	return validation.ValidateAPIServiceUpdate(obj.(*apiregistration.APIService), old.(*apiregistration.APIService))
}

type apiServerStatusStrategy struct {
	runtime.ObjectTyper
	names.NameGenerator
}

func NewStatusStrategy(typer runtime.ObjectTyper) apiServerStatusStrategy {
	return apiServerStatusStrategy{typer, names.SimpleNameGenerator}
}

func (apiServerStatusStrategy) NamespaceScoped() bool {
	return false
}

func (apiServerStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
	newAPIService := obj.(*apiregistration.APIService)
	oldAPIService := old.(*apiregistration.APIService)
	newAPIService.Spec = oldAPIService.Spec
	newAPIService.Labels = oldAPIService.Labels
	newAPIService.Annotations = oldAPIService.Annotations
	newAPIService.Finalizers = oldAPIService.Finalizers
	newAPIService.OwnerReferences = oldAPIService.OwnerReferences
}

func (apiServerStatusStrategy) AllowCreateOnUpdate() bool {
	return false
}

func (apiServerStatusStrategy) AllowUnconditionalUpdate() bool {
	return false
}

func (apiServerStatusStrategy) Canonicalize(obj runtime.Object) {
}

func (apiServerStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
	return validation.ValidateAPIServiceStatusUpdate(obj.(*apiregistration.APIService), old.(*apiregistration.APIService))
}

func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
	apiserver, ok := obj.(*apiregistration.APIService)
	if !ok {
		return nil, nil, fmt.Errorf("given object is not a APIService.")
	}
	return labels.Set(apiserver.ObjectMeta.Labels), APIServiceToSelectableFields(apiserver), nil
}

// MatchAPIService is the filter used by the generic etcd backend to watch events
// from etcd to clients of the apiserver only interested in specific labels/fields.
func MatchAPIService(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
	return storage.SelectionPredicate{
		Label:    label,
		Field:    field,
		GetAttrs: GetAttrs,
	}
}

// APIServiceToSelectableFields returns a field set that represents the object.
func APIServiceToSelectableFields(obj *apiregistration.APIService) fields.Set {
	return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true)
}
<commit_msg>Allow initialization of resources<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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 apiservice

import (
	"fmt"

	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/validation/field"
	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
	"k8s.io/apiserver/pkg/registry/generic"
	"k8s.io/apiserver/pkg/storage"
	"k8s.io/apiserver/pkg/storage/names"

	"k8s.io/kube-aggregator/pkg/apis/apiregistration"
	"k8s.io/kube-aggregator/pkg/apis/apiregistration/validation"
)

type apiServerStrategy struct {
	runtime.ObjectTyper
	names.NameGenerator
}

func NewStrategy(typer runtime.ObjectTyper) apiServerStrategy {
	return apiServerStrategy{typer, names.SimpleNameGenerator}
}

func (apiServerStrategy) NamespaceScoped() bool {
	return false
}

func (apiServerStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
	apiservice := obj.(*apiregistration.APIService)
	apiservice.Status = apiregistration.APIServiceStatus{}
}

func (apiServerStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
	newAPIService := obj.(*apiregistration.APIService)
	oldAPIService := old.(*apiregistration.APIService)
	newAPIService.Status = oldAPIService.Status
}

func (apiServerStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
	return validation.ValidateAPIService(obj.(*apiregistration.APIService))
}

func (apiServerStrategy) AllowCreateOnUpdate() bool {
	return false
}

func (apiServerStrategy) AllowUnconditionalUpdate() bool {
	return false
}

func (apiServerStrategy) Canonicalize(obj runtime.Object) {
}

func (apiServerStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
	return validation.ValidateAPIServiceUpdate(obj.(*apiregistration.APIService), old.(*apiregistration.APIService))
}

type apiServerStatusStrategy struct {
	runtime.ObjectTyper
	names.NameGenerator
}

func NewStatusStrategy(typer runtime.ObjectTyper) apiServerStatusStrategy {
	return apiServerStatusStrategy{typer, names.SimpleNameGenerator}
}

func (apiServerStatusStrategy) NamespaceScoped() bool {
	return false
}

func (apiServerStatusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
	newAPIService := obj.(*apiregistration.APIService)
	oldAPIService := old.(*apiregistration.APIService)
	newAPIService.Spec = oldAPIService.Spec
	newAPIService.Labels = oldAPIService.Labels
	newAPIService.Annotations = oldAPIService.Annotations
	newAPIService.Finalizers = oldAPIService.Finalizers
	newAPIService.OwnerReferences = oldAPIService.OwnerReferences
}

func (apiServerStatusStrategy) AllowCreateOnUpdate() bool {
	return false
}

func (apiServerStatusStrategy) AllowUnconditionalUpdate() bool {
	return false
}

func (apiServerStatusStrategy) Canonicalize(obj runtime.Object) {
}

func (apiServerStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
	return validation.ValidateAPIServiceStatusUpdate(obj.(*apiregistration.APIService), old.(*apiregistration.APIService))
}

func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
	apiserver, ok := obj.(*apiregistration.APIService)
	if !ok {
		return nil, nil, false, fmt.Errorf("given object is not a APIService.")
	}
	return labels.Set(apiserver.ObjectMeta.Labels), APIServiceToSelectableFields(apiserver), apiserver.Initializers != nil, nil
}

// MatchAPIService is the filter used by the generic etcd backend to watch events
// from etcd to clients of the apiserver only interested in specific labels/fields.
func MatchAPIService(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
	return storage.SelectionPredicate{
		Label:    label,
		Field:    field,
		GetAttrs: GetAttrs,
	}
}

// APIServiceToSelectableFields returns a field set that represents the object.
func APIServiceToSelectableFields(obj *apiregistration.APIService) fields.Set {
	return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true)
}
<|endoftext|>


<commit_before>package dns_messages

import (
	"math/rand"
	"time"
)

type Message struct {
	head       []byte
	question   []byte
	answers    []byte
	authority  []byte
	additional []byte
}

func NametoQuery(name []byte) ([]byte, []byte) {
	src := rand.NewSource(time.Now().UnixNano())
	gen := rand.New(src)

	var id []byte
	id = make([]byte, 4)
	gen.Read(id)

	qr := []byte{1}
	opcode := []byte{0, 0, 0, 0}
	aa := []byte{0}
	tc := []byte{0}
	rd := []byte{1}
	ra := []byte{0}
	z := []byte{0, 0, 0}
	rcode := []byte{0, 0, 0, 0}
	qdcount := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
	ancount := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	nscount := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	arcount := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

	header := []byte{}
	headerComponents := [][]byte{id, qr, opcode, aa, tc, rd, ra, z, rcode, qdcount, ancount, nscount, arcount}
	for _, elt := range headerComponents {
		header = append(header, elt...)
	}

	qlength := uint8(len(name))

	message := append(append(header, qlength), name...)

	return id, message
}
<commit_msg>Changed implementation of NametoQuery to return the struct<commit_after>package dns_messages

import (
	"math/rand"
	"time"
)

type Message struct {
	head       []byte
	question   []byte
	answers    []byte
	authority  []byte
	additional []byte
}

func NametoQuery(name []byte) ([]byte, Message) {
	src := rand.NewSource(time.Now().UnixNano())
	gen := rand.New(src)

	var id []byte
	id = make([]byte, 4)
	gen.Read(id)

	qr := []byte{1}
	opcode := []byte{0, 0, 0, 0}
	aa := []byte{0}
	tc := []byte{0}
	rd := []byte{1}
	ra := []byte{0}
	z := []byte{0, 0, 0}
	rcode := []byte{0, 0, 0, 0}
	qdcount := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
	ancount := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	nscount := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	arcount := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

	header := []byte{}
	headerComponents := [][]byte{id, qr, opcode, aa, tc, rd, ra, z, rcode, qdcount, ancount, nscount, arcount}
	for _, elt := range headerComponents {
		header = append(header, elt...)
	}

	qlength := uint8(len(name))

	message := Message{
		head:       header,
		question:   append(append([]byte{}, qlength), name...),
		answers:    []byte{},
		authority:  []byte{},
		additional: []byte{}}

	return id, message
}
<|endoftext|>


<commit_before>package euler

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"

	"github.com/Nooby/EulerGo/lib/data"
)

//go:generate esc -o data/static.go -ignore "static.go" -pkg data data

var (
	fs           http.FileSystem
	descriptions []string
	solutions    []string
	resources    map[int]interface{}
)

func init() {
	err := initProjectEuler()
	if err != nil {
		log.Fatal(err)
	}
}

func Verify(challenge int, solution string) (bool, error) {
	if len(solutions) < challenge {
		return false, fmt.Errorf("solution not available for challenge %v", challenge)
	}

	sol := solutions[challenge-1]
	return sol == solution, nil
}

func initProjectEuler() error {
	fs = data.FS(false)
	err := initDescriptions()
	if err != nil {
		return fmt.Errorf("problem descriptions not available: %v", err)
	}
	err = initSolutions()
	if err != nil {
		return fmt.Errorf("problem solutions not available: %v", err)
	}
	err = initResources()
	if err != nil {
		return fmt.Errorf("problem resources not available: %v", err)
	}
	return nil
}

func initDescriptions() error {
	file, err := fs.Open("/data/problems.txt")
	if err != nil {
		return fmt.Errorf("couldn't open problems descriptions: %v", err)
	}
	defer file.Close()

	text, err := ioutil.ReadAll(file)
	if err != nil {
		return fmt.Errorf("couldn't read problems file: %v", err)
	}
	descriptions = strings.Split(string(text), "\n\n\n")
	log.Printf("%v Descriptions Parsed.", len(descriptions))

	return nil
}

func initSolutions() error {
	solutions = make([]string, 0)
	file, err := fs.Open("/data/solutions.txt")
	if err != nil {
		return fmt.Errorf("couldn't open solution file: %v", err)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		splitLine := strings.Split(scanner.Text(), " ")
		solutions = append(solutions, splitLine[1])
	}
	if err := scanner.Err(); err != nil {
		return fmt.Errorf("couldn't read problems file: %v", err)
	}
	log.Printf("%v Solutions Parsed.", len(solutions))

	return nil
}

func initResources() error {
	file, err := fs.Open("/data/resources.json")
	if err != nil {
		return fmt.Errorf("couldn't open resources file: %v", err)
	}
	defer file.Close()

	text, err := ioutil.ReadAll(file)
	if err != nil {
		return fmt.Errorf("couldn't read resources file: %v", err)
	}

	json.Unmarshal(text, &resources)
	log.Printf("%v Resources Parsed.", len(resources))

	for _, v := range [2]int{252, 255} {
		fmt.Printf("Key: %v, Value: %v\n", v, resources[v])
		var t interface{}
		t = resources[v]
		switch t := t.(type) {
		default:
			fmt.Printf("unexpected type %T\n", t) // %T prints whatever type t has
		case string:
			fmt.Printf("string %v\n", t)
		case []interface{}:
			fmt.Printf("[]string %v\n", t) // t has type int
			for i := range t {
				fmt.Printf("element %v\n", t[i])
			}

		}
	}

	return nil
}
<commit_msg>Fixed Verify Range Check and not available challenge<commit_after>package euler

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"

	"github.com/Nooby/EulerGo/lib/data"
)

//go:generate esc -o data/static.go -ignore "static.go" -pkg data data

var (
	fs           http.FileSystem
	descriptions []string
	solutions    []string
	resources    map[int]interface{}
)

func init() {
	err := initProjectEuler()
	if err != nil {
		log.Fatal(err)
	}
}

func Verify(challenge int, solution string) (bool, error) {
	if challenge <= 0 || challenge >= len(solutions) {
		return false, fmt.Errorf("solution not available for challenge %v", challenge)
	}

	sol := solutions[challenge-1]
	if sol == "" {
		return false, fmt.Errorf("solution not available for challenge %v", challenge)
	}
	return sol == solution, nil
}

func initProjectEuler() error {
	fs = data.FS(false)
	err := initDescriptions()
	if err != nil {
		return fmt.Errorf("problem descriptions not available: %v", err)
	}
	err = initSolutions()
	if err != nil {
		return fmt.Errorf("problem solutions not available: %v", err)
	}
	err = initResources()
	if err != nil {
		return fmt.Errorf("problem resources not available: %v", err)
	}
	return nil
}

func initDescriptions() error {
	file, err := fs.Open("/data/problems.txt")
	if err != nil {
		return fmt.Errorf("couldn't open problems descriptions: %v", err)
	}
	defer file.Close()

	text, err := ioutil.ReadAll(file)
	if err != nil {
		return fmt.Errorf("couldn't read problems file: %v", err)
	}
	descriptions = strings.Split(string(text), "\n\n\n")
	log.Printf("%v Descriptions Parsed.", len(descriptions))

	return nil
}

func initSolutions() error {
	solutions = make([]string, 0)
	file, err := fs.Open("/data/solutions.txt")
	if err != nil {
		return fmt.Errorf("couldn't open solution file: %v", err)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		splitLine := strings.Split(scanner.Text(), " ")
		solutions = append(solutions, splitLine[1])
	}
	if err := scanner.Err(); err != nil {
		return fmt.Errorf("couldn't read problems file: %v", err)
	}
	log.Printf("%v Solutions Parsed.", len(solutions))

	return nil
}

func initResources() error {
	file, err := fs.Open("/data/resources.json")
	if err != nil {
		return fmt.Errorf("couldn't open resources file: %v", err)
	}
	defer file.Close()

	text, err := ioutil.ReadAll(file)
	if err != nil {
		return fmt.Errorf("couldn't read resources file: %v", err)
	}

	json.Unmarshal(text, &resources)
	log.Printf("%v Resources Parsed.", len(resources))

	for _, v := range [2]int{252, 255} {
		fmt.Printf("Key: %v, Value: %v\n", v, resources[v])
		var t interface{}
		t = resources[v]
		switch t := t.(type) {
		default:
			fmt.Printf("unexpected type %T\n", t) // %T prints whatever type t has
		case string:
			fmt.Printf("string %v\n", t)
		case []interface{}:
			fmt.Printf("[]string %v\n", t) // t has type int
			for i := range t {
				fmt.Printf("element %v\n", t[i])
			}

		}
	}

	return nil
}
<|endoftext|>


<commit_before>package secretservice

import (
	"math/big"
	"time"

	dbus "github.com/keybase/dbus"
	errors "github.com/pkg/errors"
)

// SecretServiceInterface
const SecretServiceInterface = "org.freedesktop.secrets"

// SecretServiceObjectPath
const SecretServiceObjectPath dbus.ObjectPath = "/org/freedesktop/secrets"

// DefaultCollection need not necessarily exist in the user's keyring.
const DefaultCollection dbus.ObjectPath = "/org/freedesktop/secrets/aliases/default"

// AuthenticationMode
type AuthenticationMode string

// AuthenticationInsecurePlain
const AuthenticationInsecurePlain AuthenticationMode = "plain"

// AuthenticationDHAES
const AuthenticationDHAES AuthenticationMode = "dh-ietf1024-sha256-aes128-cbc-pkcs7"

// NilFlags
const NilFlags = 0

// Attributes
type Attributes map[string]string

// Secret
type Secret struct {
	Session     dbus.ObjectPath
	Parameters  []byte
	Value       []byte
	ContentType string
}

// PromptCompletedResult
type PromptCompletedResult struct {
	Dismissed bool
	Paths     dbus.Variant
}

// SecretService
type SecretService struct {
	conn               *dbus.Conn
	signalCh           <-chan *dbus.Signal
	sessionOpenTimeout time.Duration
}

// Session
type Session struct {
	Mode    AuthenticationMode
	Path    dbus.ObjectPath
	Public  *big.Int
	Private *big.Int
	AESKey  []byte
}

// DefaultSessionOpenTimeout
const DefaultSessionOpenTimeout = 10 * time.Second

// NewService
func NewService() (*SecretService, error) {
	conn, err := dbus.ConnectSessionBus()
	if err != nil {
		return nil, errors.Wrap(err, "failed to open dbus connection")
	}
	signalCh := make(chan *dbus.Signal, 16)
	conn.Signal(signalCh)
	return &SecretService{conn: conn, signalCh: signalCh, sessionOpenTimeout: DefaultSessionOpenTimeout}, nil
}

// SetSessionOpenTimeout
func (s *SecretService) SetSessionOpenTimeout(d time.Duration) {
	s.sessionOpenTimeout = d
}

// ServiceObj
func (s *SecretService) ServiceObj() dbus.BusObject {
	return s.conn.Object(SecretServiceInterface, SecretServiceObjectPath)
}

// Obj
func (s *SecretService) Obj(path dbus.ObjectPath) dbus.BusObject {
	return s.conn.Object(SecretServiceInterface, path)
}

type sessionOpenResponse struct {
	algorithmOutput dbus.Variant
	path            dbus.ObjectPath
}

func (s *SecretService) openSessionRaw(mode AuthenticationMode, sessionAlgorithmInput dbus.Variant) (resp sessionOpenResponse, err error) {
	err = s.ServiceObj().
		Call("org.freedesktop.Secret.Service.OpenSession", NilFlags, mode, sessionAlgorithmInput).
		Store(&resp.algorithmOutput, &resp.path)
	return resp, errors.Wrap(err, "failed to open secretservice session")
}

// OpenSession
func (s *SecretService) OpenSession(mode AuthenticationMode) (session *Session, err error) {
	var sessionAlgorithmInput dbus.Variant

	session = new(Session)

	session.Mode = mode

	switch mode {
	case AuthenticationInsecurePlain:
		sessionAlgorithmInput = dbus.MakeVariant("")
	case AuthenticationDHAES:
		group := rfc2409SecondOakleyGroup()
		private, public, err := group.NewKeypair()
		if err != nil {
			return nil, err
		}
		session.Private = private
		session.Public = public
		sessionAlgorithmInput = dbus.MakeVariant(public.Bytes()) // math/big.Int.Bytes is big endian
	default:
		return nil, errors.Errorf("unknown authentication mode %v", mode)
	}

	sessionOpenCh := make(chan sessionOpenResponse)
	errCh := make(chan error)
	go func() {
		sessionOpenResponse, err := s.openSessionRaw(mode, sessionAlgorithmInput)
		if err != nil {
			errCh <- err
		} else {
			sessionOpenCh <- sessionOpenResponse
		}
	}()

	var sessionAlgorithmOutput dbus.Variant
	// NOTE: If the timeout case is reached, the above goroutine is leaked.
	// This is not terrible because D-Bus calls have an internal 2-mintue
	// timeout, so the goroutine will finish eventually. If two OpenSessions
	// are called at the saime time, they'll be on different channels so
	// they won't interfere with each other.
	select {
	case resp := <-sessionOpenCh:
		sessionAlgorithmOutput = resp.algorithmOutput
		session.Path = resp.path
	case err := <-errCh:
		return nil, err
	case <-time.After(s.sessionOpenTimeout):
		return nil, errors.Errorf("timed out after %s", s.sessionOpenTimeout)
	}

	switch mode {
	case AuthenticationInsecurePlain:
	case AuthenticationDHAES:
		theirPublicBigEndian, ok := sessionAlgorithmOutput.Value().([]byte)
		if !ok {
			return nil, errors.Errorf("failed to coerce algorithm output value to byteslice")
		}
		group := rfc2409SecondOakleyGroup()
		theirPublic := new(big.Int)
		theirPublic.SetBytes(theirPublicBigEndian)
		aesKey, err := group.keygenHKDFSHA256AES128(theirPublic, session.Private)
		if err != nil {
			return nil, err
		}
		session.AESKey = aesKey
	default:
		return nil, errors.Errorf("unknown authentication mode %v", mode)
	}

	return session, nil
}

// CloseSession
func (s *SecretService) CloseSession(session *Session) {
	s.Obj(session.Path).Call("org.freedesktop.Secret.Session.Close", NilFlags)
}

// SearchColleciton
func (s *SecretService) SearchCollection(collection dbus.ObjectPath, attributes Attributes) (items []dbus.ObjectPath, err error) {
	err = s.Obj(collection).
		Call("org.freedesktop.Secret.Collection.SearchItems", NilFlags, attributes).
		Store(&items)
	if err != nil {
		return nil, errors.Wrap(err, "failed to search collection")
	}
	return items, nil
}

// ReplaceBehavior
type ReplaceBehavior int

// ReplaceBehaviorDoNotReplace
const ReplaceBehaviorDoNotReplace = 0

// ReplaceBehaviorReplace
const ReplaceBehaviorReplace = 1

// CreateItem
func (s *SecretService) CreateItem(collection dbus.ObjectPath, properties map[string]dbus.Variant, secret Secret, replaceBehavior ReplaceBehavior) (item dbus.ObjectPath, err error) {
	var replace bool
	switch replaceBehavior {
	case ReplaceBehaviorDoNotReplace:
		replace = false
	case ReplaceBehaviorReplace:
		replace = true
	default:
		return "", errors.Errorf("unknown replace behavior %v", replaceBehavior)
	}

	var prompt dbus.ObjectPath
	err = s.Obj(collection).
		Call("org.freedesktop.Secret.Collection.CreateItem", NilFlags, properties, secret, replace).
		Store(&item, &prompt)
	if err != nil {
		return "", errors.Wrap(err, "failed to create item")
	}
	_, err = s.PromptAndWait(prompt)
	if err != nil {
		return "", err
	}
	return item, nil
}

// DeleteItem
func (s *SecretService) DeleteItem(item dbus.ObjectPath) (err error) {
	var prompt dbus.ObjectPath
	err = s.Obj(item).
		Call("org.freedesktop.Secret.Item.Delete", NilFlags).
		Store(&prompt)
	if err != nil {
		return errors.Wrap(err, "failed to delete item")
	}
	_, err = s.PromptAndWait(prompt)
	if err != nil {
		return err
	}
	return nil
}

// GetAttributes
func (s *SecretService) GetAttributes(item dbus.ObjectPath) (attributes Attributes, err error) {
	attributesV, err := s.Obj(item).GetProperty("org.freedesktop.Secret.Item.Attributes")
	if err != nil {
		return nil, errors.Wrap(err, "failed to get attributes")
	}
	attributesMap, ok := attributesV.Value().(map[string]string)
	if !ok {
		return nil, errors.Errorf("failed to coerce item attributes")
	}
	return Attributes(attributesMap), nil
}

// GetSecret
func (s *SecretService) GetSecret(item dbus.ObjectPath, session Session) (secretPlaintext []byte, err error) {
	var secretI []interface{}
	err = s.Obj(item).
		Call("org.freedesktop.Secret.Item.GetSecret", NilFlags, session.Path).
		Store(&secretI)
	if err != nil {
		return nil, errors.Wrap(err, "failed to get secret")
	}
	secret := new(Secret)
	err = dbus.Store(secretI, &secret.Session, &secret.Parameters, &secret.Value, &secret.ContentType)
	if err != nil {
		return nil, errors.Wrap(err, "failed to unmarshal get secret result")
	}

	switch session.Mode {
	case AuthenticationInsecurePlain:
		secretPlaintext = secret.Value
	case AuthenticationDHAES:
		plaintext, err := unauthenticatedAESCBCDecrypt(secret.Parameters, secret.Value, session.AESKey)
		if err != nil {
			return nil, nil
		}
		secretPlaintext = plaintext
	default:
		return nil, errors.Errorf("cannot make secret for authentication mode %v", session.Mode)
	}

	return secretPlaintext, nil
}

// NullPrompt
const NullPrompt = "/"

// Unlock
func (s *SecretService) Unlock(items []dbus.ObjectPath) (err error) {
	var dummy []dbus.ObjectPath
	var prompt dbus.ObjectPath
	err = s.ServiceObj().
		Call("org.freedesktop.Secret.Service.Unlock", NilFlags, items).
		Store(&dummy, &prompt)
	if err != nil {
		return errors.Wrap(err, "failed to unlock items")
	}
	_, err = s.PromptAndWait(prompt)
	if err != nil {
		return errors.Wrap(err, "failed to prompt")
	}
	return nil
}

// LockItems
func (s *SecretService) LockItems(items []dbus.ObjectPath) (err error) {
	var dummy []dbus.ObjectPath
	var prompt dbus.ObjectPath
	err = s.ServiceObj().
		Call("org.freedesktop.Secret.Service.Lock", NilFlags, items).
		Store(&dummy, &prompt)
	if err != nil {
		return errors.Wrap(err, "failed to lock items")
	}
	_, err = s.PromptAndWait(prompt)
	if err != nil {
		return errors.Wrap(err, "failed to prompt")
	}
	return nil
}

// PromptDismissedError
type PromptDismissedError struct {
	err error
}

// Error
func (p PromptDismissedError) Error() string {
	return p.err.Error()
}

// PromptAndWait is NOT thread-safe.
func (s *SecretService) PromptAndWait(prompt dbus.ObjectPath) (paths *dbus.Variant, err error) {
	if prompt == NullPrompt {
		return nil, nil
	}
	call := s.Obj(prompt).Call("org.freedesktop.Secret.Prompt.Prompt", NilFlags, "Keyring Prompt")
	if call.Err != nil {
		return nil, errors.Wrap(err, "failed to prompt")
	}
	for {
		var result PromptCompletedResult
		select {
		case signal, ok := <-s.signalCh:
			if !ok {
				return nil, errors.New("prompt channel closed")
			}
			if signal == nil {
				continue
			}
			if signal.Name != "org.freedesktop.Secret.Prompt.Completed" {
				continue
			}
			err = dbus.Store(signal.Body, &result.Dismissed, &result.Paths)
			if err != nil {
				return nil, errors.Wrap(err, "failed to unmarshal prompt result")
			}
			if result.Dismissed {
				return nil, PromptDismissedError{errors.New("prompt dismissed")}
			}
			return &result.Paths, nil
		case <-time.After(30 * time.Second):
			return nil, errors.New("prompt timed out")
		}
	}
}

// NewSecretProperties
func NewSecretProperties(label string, attributes map[string]string) map[string]dbus.Variant {
	return map[string]dbus.Variant{
		"org.freedesktop.Secret.Item.Label":      dbus.MakeVariant(label),
		"org.freedesktop.Secret.Item.Attributes": dbus.MakeVariant(attributes),
	}
}

// NewSecret
func (session *Session) NewSecret(secretBytes []byte) (Secret, error) {
	switch session.Mode {
	case AuthenticationInsecurePlain:
		return Secret{
			Session:     session.Path,
			Parameters:  nil,
			Value:       secretBytes,
			ContentType: "application/octet-stream",
		}, nil
	case AuthenticationDHAES:
		iv, ciphertext, err := unauthenticatedAESCBCEncrypt(secretBytes, session.AESKey)
		if err != nil {
			return Secret{}, err
		}
		return Secret{
			Session:     session.Path,
			Parameters:  iv,
			Value:       ciphertext,
			ContentType: "application/octet-stream",
		}, nil
	default:
		return Secret{}, errors.Errorf("cannot make secret for authentication mode %v", session.Mode)
	}
}
<commit_msg>add signal match (#85)<commit_after>package secretservice

import (
	"math/big"
	"time"

	dbus "github.com/keybase/dbus"
	errors "github.com/pkg/errors"
)

// SecretServiceInterface
const SecretServiceInterface = "org.freedesktop.secrets"

// SecretServiceObjectPath
const SecretServiceObjectPath dbus.ObjectPath = "/org/freedesktop/secrets"

// DefaultCollection need not necessarily exist in the user's keyring.
const DefaultCollection dbus.ObjectPath = "/org/freedesktop/secrets/aliases/default"

// AuthenticationMode
type AuthenticationMode string

// AuthenticationInsecurePlain
const AuthenticationInsecurePlain AuthenticationMode = "plain"

// AuthenticationDHAES
const AuthenticationDHAES AuthenticationMode = "dh-ietf1024-sha256-aes128-cbc-pkcs7"

// NilFlags
const NilFlags = 0

// Attributes
type Attributes map[string]string

// Secret
type Secret struct {
	Session     dbus.ObjectPath
	Parameters  []byte
	Value       []byte
	ContentType string
}

// PromptCompletedResult
type PromptCompletedResult struct {
	Dismissed bool
	Paths     dbus.Variant
}

// SecretService
type SecretService struct {
	conn               *dbus.Conn
	signalCh           <-chan *dbus.Signal
	sessionOpenTimeout time.Duration
}

// Session
type Session struct {
	Mode    AuthenticationMode
	Path    dbus.ObjectPath
	Public  *big.Int
	Private *big.Int
	AESKey  []byte
}

// DefaultSessionOpenTimeout
const DefaultSessionOpenTimeout = 10 * time.Second

// NewService
func NewService() (*SecretService, error) {
	conn, err := dbus.ConnectSessionBus()
	if err != nil {
		return nil, errors.Wrap(err, "failed to open dbus connection")
	}
	signalCh := make(chan *dbus.Signal, 16)
	conn.Signal(signalCh)
	_ = conn.AddMatchSignal(dbus.WithMatchOption("org.freedesktop.Secret.Prompt", "Completed"))
	return &SecretService{conn: conn, signalCh: signalCh, sessionOpenTimeout: DefaultSessionOpenTimeout}, nil
}

// SetSessionOpenTimeout
func (s *SecretService) SetSessionOpenTimeout(d time.Duration) {
	s.sessionOpenTimeout = d
}

// ServiceObj
func (s *SecretService) ServiceObj() dbus.BusObject {
	return s.conn.Object(SecretServiceInterface, SecretServiceObjectPath)
}

// Obj
func (s *SecretService) Obj(path dbus.ObjectPath) dbus.BusObject {
	return s.conn.Object(SecretServiceInterface, path)
}

type sessionOpenResponse struct {
	algorithmOutput dbus.Variant
	path            dbus.ObjectPath
}

func (s *SecretService) openSessionRaw(mode AuthenticationMode, sessionAlgorithmInput dbus.Variant) (resp sessionOpenResponse, err error) {
	err = s.ServiceObj().
		Call("org.freedesktop.Secret.Service.OpenSession", NilFlags, mode, sessionAlgorithmInput).
		Store(&resp.algorithmOutput, &resp.path)
	return resp, errors.Wrap(err, "failed to open secretservice session")
}

// OpenSession
func (s *SecretService) OpenSession(mode AuthenticationMode) (session *Session, err error) {
	var sessionAlgorithmInput dbus.Variant

	session = new(Session)

	session.Mode = mode

	switch mode {
	case AuthenticationInsecurePlain:
		sessionAlgorithmInput = dbus.MakeVariant("")
	case AuthenticationDHAES:
		group := rfc2409SecondOakleyGroup()
		private, public, err := group.NewKeypair()
		if err != nil {
			return nil, err
		}
		session.Private = private
		session.Public = public
		sessionAlgorithmInput = dbus.MakeVariant(public.Bytes()) // math/big.Int.Bytes is big endian
	default:
		return nil, errors.Errorf("unknown authentication mode %v", mode)
	}

	sessionOpenCh := make(chan sessionOpenResponse)
	errCh := make(chan error)
	go func() {
		sessionOpenResponse, err := s.openSessionRaw(mode, sessionAlgorithmInput)
		if err != nil {
			errCh <- err
		} else {
			sessionOpenCh <- sessionOpenResponse
		}
	}()

	var sessionAlgorithmOutput dbus.Variant
	// NOTE: If the timeout case is reached, the above goroutine is leaked.
	// This is not terrible because D-Bus calls have an internal 2-mintue
	// timeout, so the goroutine will finish eventually. If two OpenSessions
	// are called at the saime time, they'll be on different channels so
	// they won't interfere with each other.
	select {
	case resp := <-sessionOpenCh:
		sessionAlgorithmOutput = resp.algorithmOutput
		session.Path = resp.path
	case err := <-errCh:
		return nil, err
	case <-time.After(s.sessionOpenTimeout):
		return nil, errors.Errorf("timed out after %s", s.sessionOpenTimeout)
	}

	switch mode {
	case AuthenticationInsecurePlain:
	case AuthenticationDHAES:
		theirPublicBigEndian, ok := sessionAlgorithmOutput.Value().([]byte)
		if !ok {
			return nil, errors.Errorf("failed to coerce algorithm output value to byteslice")
		}
		group := rfc2409SecondOakleyGroup()
		theirPublic := new(big.Int)
		theirPublic.SetBytes(theirPublicBigEndian)
		aesKey, err := group.keygenHKDFSHA256AES128(theirPublic, session.Private)
		if err != nil {
			return nil, err
		}
		session.AESKey = aesKey
	default:
		return nil, errors.Errorf("unknown authentication mode %v", mode)
	}

	return session, nil
}

// CloseSession
func (s *SecretService) CloseSession(session *Session) {
	s.Obj(session.Path).Call("org.freedesktop.Secret.Session.Close", NilFlags)
}

// SearchColleciton
func (s *SecretService) SearchCollection(collection dbus.ObjectPath, attributes Attributes) (items []dbus.ObjectPath, err error) {
	err = s.Obj(collection).
		Call("org.freedesktop.Secret.Collection.SearchItems", NilFlags, attributes).
		Store(&items)
	if err != nil {
		return nil, errors.Wrap(err, "failed to search collection")
	}
	return items, nil
}

// ReplaceBehavior
type ReplaceBehavior int

// ReplaceBehaviorDoNotReplace
const ReplaceBehaviorDoNotReplace = 0

// ReplaceBehaviorReplace
const ReplaceBehaviorReplace = 1

// CreateItem
func (s *SecretService) CreateItem(collection dbus.ObjectPath, properties map[string]dbus.Variant, secret Secret, replaceBehavior ReplaceBehavior) (item dbus.ObjectPath, err error) {
	var replace bool
	switch replaceBehavior {
	case ReplaceBehaviorDoNotReplace:
		replace = false
	case ReplaceBehaviorReplace:
		replace = true
	default:
		return "", errors.Errorf("unknown replace behavior %v", replaceBehavior)
	}

	var prompt dbus.ObjectPath
	err = s.Obj(collection).
		Call("org.freedesktop.Secret.Collection.CreateItem", NilFlags, properties, secret, replace).
		Store(&item, &prompt)
	if err != nil {
		return "", errors.Wrap(err, "failed to create item")
	}
	_, err = s.PromptAndWait(prompt)
	if err != nil {
		return "", err
	}
	return item, nil
}

// DeleteItem
func (s *SecretService) DeleteItem(item dbus.ObjectPath) (err error) {
	var prompt dbus.ObjectPath
	err = s.Obj(item).
		Call("org.freedesktop.Secret.Item.Delete", NilFlags).
		Store(&prompt)
	if err != nil {
		return errors.Wrap(err, "failed to delete item")
	}
	_, err = s.PromptAndWait(prompt)
	if err != nil {
		return err
	}
	return nil
}

// GetAttributes
func (s *SecretService) GetAttributes(item dbus.ObjectPath) (attributes Attributes, err error) {
	attributesV, err := s.Obj(item).GetProperty("org.freedesktop.Secret.Item.Attributes")
	if err != nil {
		return nil, errors.Wrap(err, "failed to get attributes")
	}
	attributesMap, ok := attributesV.Value().(map[string]string)
	if !ok {
		return nil, errors.Errorf("failed to coerce item attributes")
	}
	return Attributes(attributesMap), nil
}

// GetSecret
func (s *SecretService) GetSecret(item dbus.ObjectPath, session Session) (secretPlaintext []byte, err error) {
	var secretI []interface{}
	err = s.Obj(item).
		Call("org.freedesktop.Secret.Item.GetSecret", NilFlags, session.Path).
		Store(&secretI)
	if err != nil {
		return nil, errors.Wrap(err, "failed to get secret")
	}
	secret := new(Secret)
	err = dbus.Store(secretI, &secret.Session, &secret.Parameters, &secret.Value, &secret.ContentType)
	if err != nil {
		return nil, errors.Wrap(err, "failed to unmarshal get secret result")
	}

	switch session.Mode {
	case AuthenticationInsecurePlain:
		secretPlaintext = secret.Value
	case AuthenticationDHAES:
		plaintext, err := unauthenticatedAESCBCDecrypt(secret.Parameters, secret.Value, session.AESKey)
		if err != nil {
			return nil, nil
		}
		secretPlaintext = plaintext
	default:
		return nil, errors.Errorf("cannot make secret for authentication mode %v", session.Mode)
	}

	return secretPlaintext, nil
}

// NullPrompt
const NullPrompt = "/"

// Unlock
func (s *SecretService) Unlock(items []dbus.ObjectPath) (err error) {
	var dummy []dbus.ObjectPath
	var prompt dbus.ObjectPath
	err = s.ServiceObj().
		Call("org.freedesktop.Secret.Service.Unlock", NilFlags, items).
		Store(&dummy, &prompt)
	if err != nil {
		return errors.Wrap(err, "failed to unlock items")
	}
	_, err = s.PromptAndWait(prompt)
	if err != nil {
		return errors.Wrap(err, "failed to prompt")
	}
	return nil
}

// LockItems
func (s *SecretService) LockItems(items []dbus.ObjectPath) (err error) {
	var dummy []dbus.ObjectPath
	var prompt dbus.ObjectPath
	err = s.ServiceObj().
		Call("org.freedesktop.Secret.Service.Lock", NilFlags, items).
		Store(&dummy, &prompt)
	if err != nil {
		return errors.Wrap(err, "failed to lock items")
	}
	_, err = s.PromptAndWait(prompt)
	if err != nil {
		return errors.Wrap(err, "failed to prompt")
	}
	return nil
}

// PromptDismissedError
type PromptDismissedError struct {
	err error
}

// Error
func (p PromptDismissedError) Error() string {
	return p.err.Error()
}

// PromptAndWait is NOT thread-safe.
func (s *SecretService) PromptAndWait(prompt dbus.ObjectPath) (paths *dbus.Variant, err error) {
	if prompt == NullPrompt {
		return nil, nil
	}
	call := s.Obj(prompt).Call("org.freedesktop.Secret.Prompt.Prompt", NilFlags, "Keyring Prompt")
	if call.Err != nil {
		return nil, errors.Wrap(err, "failed to prompt")
	}
	for {
		var result PromptCompletedResult
		select {
		case signal, ok := <-s.signalCh:
			if !ok {
				return nil, errors.New("prompt channel closed")
			}
			if signal == nil {
				continue
			}
			if signal.Name != "org.freedesktop.Secret.Prompt.Completed" {
				continue
			}
			err = dbus.Store(signal.Body, &result.Dismissed, &result.Paths)
			if err != nil {
				return nil, errors.Wrap(err, "failed to unmarshal prompt result")
			}
			if result.Dismissed {
				return nil, PromptDismissedError{errors.New("prompt dismissed")}
			}
			return &result.Paths, nil
		case <-time.After(30 * time.Second):
			return nil, errors.New("prompt timed out")
		}
	}
}

// NewSecretProperties
func NewSecretProperties(label string, attributes map[string]string) map[string]dbus.Variant {
	return map[string]dbus.Variant{
		"org.freedesktop.Secret.Item.Label":      dbus.MakeVariant(label),
		"org.freedesktop.Secret.Item.Attributes": dbus.MakeVariant(attributes),
	}
}

// NewSecret
func (session *Session) NewSecret(secretBytes []byte) (Secret, error) {
	switch session.Mode {
	case AuthenticationInsecurePlain:
		return Secret{
			Session:     session.Path,
			Parameters:  nil,
			Value:       secretBytes,
			ContentType: "application/octet-stream",
		}, nil
	case AuthenticationDHAES:
		iv, ciphertext, err := unauthenticatedAESCBCEncrypt(secretBytes, session.AESKey)
		if err != nil {
			return Secret{}, err
		}
		return Secret{
			Session:     session.Path,
			Parameters:  iv,
			Value:       ciphertext,
			ContentType: "application/octet-stream",
		}, nil
	default:
		return Secret{}, errors.Errorf("cannot make secret for authentication mode %v", session.Mode)
	}
}
<|endoftext|>


<commit_before>package server_test

import (
	"context"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	pb "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
)

// The actual test suite
var _ = t.Describe("ContainerStats", func() {
	// Prepare the sut
	BeforeEach(func() {
		beforeEach()
		setupSUT()
	})

	AfterEach(afterEach)

	t.Describe("ContainerStats", func() {
		It("should fail on invalid container", func() {
			// Given
			// When
			response, err := sut.ContainerStats(context.Background(),
				&pb.ContainerStatsRequest{})

			// Then
			Expect(err).NotTo(BeNil())
			Expect(response).To(BeNil())
		})
	})
})
<commit_msg>add stats list unit tests<commit_after>package server_test

import (
	"context"

	"github.com/cri-o/cri-o/internal/oci"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	pb "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
)

// The actual test suite
var _ = t.Describe("ContainerStats", func() {
	// Prepare the sut
	BeforeEach(func() {
		beforeEach()
		setupSUT()
	})

	AfterEach(afterEach)

	t.Describe("ContainerStats", func() {
		It("should fail on invalid container", func() {
			// Given
			// When
			response, err := sut.ContainerStats(context.Background(),
				&pb.ContainerStatsRequest{})

			// Then
			Expect(err).NotTo(BeNil())
			Expect(response).To(BeNil())
		})
	})
})

var _ = t.Describe("ContainerStatsList", func() {
	// Prepare the sut
	BeforeEach(func() {
		beforeEach()
		setupSUT()
	})

	AfterEach(afterEach)

	t.Describe("ContainerStatsList", func() {
		It("should succeed", func() {
			// Given
			addContainerAndSandbox()
			// When
			response, err := sut.ListContainerStats(context.Background(),
				&pb.ListContainerStatsRequest{})

			// Then
			Expect(err).To(BeNil())
			Expect(response).NotTo(BeNil())
			Expect(len(response.Stats)).To(Equal(1))
		})
		It("should filter stopped container", func() {
			// Given
			state := oci.ContainerState{}
			state.Status = oci.ContainerStateStopped
			testContainer.SetState(&state)
			addContainerAndSandbox()

			// When
			response, err := sut.ListContainerStats(context.Background(),
				&pb.ListContainerStatsRequest{},
			)

			// Then
			Expect(err).To(BeNil())
			Expect(response).NotTo(BeNil())
			Expect(len(response.Stats)).To(Equal(0))
		})
		It("should filter by id", func() {
			// Given
			addContainerAndSandbox()

			// When
			response, err := sut.ListContainerStats(context.Background(),
				&pb.ListContainerStatsRequest{
					Filter: &pb.ContainerStatsFilter{
						Id: "invalid",
					},
				},
			)

			// Then
			Expect(err).To(BeNil())
			Expect(response).NotTo(BeNil())
			Expect(len(response.Stats)).To(Equal(0))
		})
	})
})
<|endoftext|>


<commit_before>package bitbucket

import (
	"context"
	"crypto/sha256"
	"fmt"
	"net/http"
	"path/filepath"
	"strings"
	"sync"

	"github.com/reviewdog/reviewdog"
	"github.com/reviewdog/reviewdog/proto/rdf"
	"github.com/reviewdog/reviewdog/service/bitbucket/openapi"
)

var _ reviewdog.CommentService = &ReportAnnotator{}

const (
	// avatar from https://github.com/apps/reviewdog
	logoURL  = "https://avatars1.githubusercontent.com/in/12131"
	reporter = "reviewdog"
	// max amount of annotations in one batch call
	annotationsBatchSize = 100
)

// ReportAnnotator is a comment service for Bitbucket Code Insights reports.
//
// API:
//  https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/commit/%7Bcommit%7D/reports/%7BreportId%7D/annotations#post
//  POST /2.0/repositories/{username}/{repo_slug}/commit/{commit}/reports/{reportId}/annotations
type ReportAnnotator struct {
	cli         *openapi.APIClient
	sha         string
	owner, repo string

	muAnnotations sync.Mutex
	// store annotations in map per tool name
	// so we can create report per tool
	annotations map[string][]openapi.ReportAnnotation
	severityMap map[rdf.Severity]string

	// wd is working directory relative to root of repository.
	wd         string
	duplicates map[string]struct{}
}

// NewReportAnnotator creates new Bitbucket Report Annotator
func NewReportAnnotator(cli *openapi.APIClient, owner, repo, sha string, runners []string) *ReportAnnotator {
	// pre populate map of annotations, so we still create passed (green) report
	// if no issues found from the specific tool
	annotations := make(map[string][]openapi.ReportAnnotation, len(runners))
	for _, runner := range runners {
		if len(runner) == 0 {
			continue
		}
		annotations[runner] = []openapi.ReportAnnotation{}
	}

	return &ReportAnnotator{
		cli:         cli,
		sha:         sha,
		owner:       owner,
		repo:        repo,
		annotations: annotations,
		severityMap: map[rdf.Severity]string{
			rdf.Severity_INFO:    annotationSeverityLow,
			rdf.Severity_WARNING: annotationSeverityMedium,
			rdf.Severity_ERROR:   annotationSeverityHigh,
		},
		duplicates: map[string]struct{}{},
	}
}

// Post accepts a comment and holds it. Flush method actually posts comments to
// Bitbucket in batch.
func (r *ReportAnnotator) Post(_ context.Context, c *reviewdog.Comment) error {
	c.Result.Diagnostic.GetLocation().Path = filepath.ToSlash(
		filepath.Join(r.wd, c.Result.Diagnostic.GetLocation().GetPath()))
	r.muAnnotations.Lock()
	defer r.muAnnotations.Unlock()

	anot := r.annotationFromReviewDogComment(*c)

	// deduplicate event, because some reporters might report
	// it twice, and bitbucket api will complain on duplicated
	// external id of annotation
	if _, ok := r.duplicates[*anot.ExternalId]; !ok {
		r.annotations[c.ToolName] = append(r.annotations[c.ToolName], anot)
	}

	r.duplicates[*anot.ExternalId] = struct{}{}
	return nil
}

// Flush posts comments which has not been posted yet.
func (r *ReportAnnotator) Flush(ctx context.Context) error {
	r.muAnnotations.Lock()
	defer r.muAnnotations.Unlock()

	// create/update/annotate report per tool
	for tool, annotations := range r.annotations {
		reportID := reportID(reporter, tool)
		title := fmt.Sprintf("[%s] %s report", tool, reporter)
		if len(annotations) == 0 {
			// if no annotation, create Passed report
			if err := r.createOrUpdateReport(ctx, reportID, title, reportResultPassed); err != nil {
				return err
			}
			// and move one
			continue
		}

		// create report or update report first, with the failed status
		if err := r.createOrUpdateReport(ctx, reportID, title, reportResultFailed); err != nil {
			return err
		}

		// send annotations in batches, because of the api max payload size limit
		for start, annCount := 0, len(annotations); start < annCount; start += annotationsBatchSize {
			end := start + annotationsBatchSize

			if end > annCount {
				end = annCount
			}

			// add annotations to the report
			_, resp, err := r.cli.ReportsApi.BulkCreateOrUpdateAnnotations(
				ctx, r.owner, r.repo, r.sha, reportID,
			).Body(annotations[start:end]).Execute()

			if err := checkAPIError(err, resp, http.StatusOK); err != nil {
				return fmt.Errorf("bitbucket.BulkCreateOrUpdateAnnotations: %s", err)
			}
		}
	}

	return nil
}

func (r *ReportAnnotator) annotationFromReviewDogComment(c reviewdog.Comment) openapi.ReportAnnotation {
	a := openapi.NewReportAnnotation()
	switch c.ToolName {
	// TODO: different type of annotation based on tool?
	default:
		a.SetAnnotationType(annotationTypeCodeSmell)
	}

	// hash the output of linter and use it as external id
	a.SetExternalId(hashString(c.Result.Diagnostic.OriginalOutput))
	a.SetSummary(c.Result.Diagnostic.GetMessage())
	a.SetDetails(fmt.Sprintf(`[%s] %s`, c.ToolName, c.Result.Diagnostic.GetMessage()))
	a.SetLine(c.Result.Diagnostic.GetLocation().GetRange().GetStart().GetLine())
	a.SetPath(c.Result.Diagnostic.GetLocation().GetPath())
	if v, ok := r.severityMap[c.Result.Diagnostic.GetSeverity()]; ok {
		a.SetSeverity(v)
	}
	if link := c.Result.Diagnostic.GetCode().GetUrl(); link != "" {
		a.SetLink(link)
	}

	return *a
}

func (r *ReportAnnotator) createOrUpdateReport(ctx context.Context, redportID, title, reportStatus string) error {
	var report = openapi.NewReport()
	report.SetTitle(title)
	// TODO: different report types?
	report.SetReportType(reportTypeBug)
	report.SetReporter(reporter)
	report.SetLogoUrl(logoURL)
	report.SetResult(reportStatus)
	report.SetDetails("Woof-Woof! This report generated for you by reviewdog")

	_, resp, err := r.cli.ReportsApi.CreateOrUpdateReport(
		ctx, r.owner, r.repo, r.sha, redportID,
	).Body(*report).Execute()

	if err := checkAPIError(err, resp, http.StatusOK); err != nil {
		return fmt.Errorf("bitbucket.CreateOrUpdateReport: %s", err)
	}

	return nil
}

func hashString(str string) string {
	h := sha256.New()
	_, _ = h.Write([]byte(str))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func reportID(ids ...string) string {
	return strings.ReplaceAll(strings.ToLower(strings.Join(ids, "-")), " ", "_")
}
<commit_msg>add different message for the Passed reports<commit_after>package bitbucket

import (
	"context"
	"crypto/sha256"
	"fmt"
	"net/http"
	"path/filepath"
	"strings"
	"sync"

	"github.com/reviewdog/reviewdog"
	"github.com/reviewdog/reviewdog/proto/rdf"
	"github.com/reviewdog/reviewdog/service/bitbucket/openapi"
)

var _ reviewdog.CommentService = &ReportAnnotator{}

const (
	// avatar from https://github.com/apps/reviewdog
	logoURL  = "https://avatars1.githubusercontent.com/in/12131"
	reporter = "reviewdog"
	// max amount of annotations in one batch call
	annotationsBatchSize = 100
)

// ReportAnnotator is a comment service for Bitbucket Code Insights reports.
//
// API:
//  https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/commit/%7Bcommit%7D/reports/%7BreportId%7D/annotations#post
//  POST /2.0/repositories/{username}/{repo_slug}/commit/{commit}/reports/{reportId}/annotations
type ReportAnnotator struct {
	cli         *openapi.APIClient
	sha         string
	owner, repo string

	muAnnotations sync.Mutex
	// store annotations in map per tool name
	// so we can create report per tool
	annotations map[string][]openapi.ReportAnnotation
	severityMap map[rdf.Severity]string

	// wd is working directory relative to root of repository.
	wd         string
	duplicates map[string]struct{}
}

// NewReportAnnotator creates new Bitbucket Report Annotator
func NewReportAnnotator(cli *openapi.APIClient, owner, repo, sha string, runners []string) *ReportAnnotator {
	// pre populate map of annotations, so we still create passed (green) report
	// if no issues found from the specific tool
	annotations := make(map[string][]openapi.ReportAnnotation, len(runners))
	for _, runner := range runners {
		if len(runner) == 0 {
			continue
		}
		annotations[runner] = []openapi.ReportAnnotation{}
	}

	return &ReportAnnotator{
		cli:         cli,
		sha:         sha,
		owner:       owner,
		repo:        repo,
		annotations: annotations,
		severityMap: map[rdf.Severity]string{
			rdf.Severity_INFO:    annotationSeverityLow,
			rdf.Severity_WARNING: annotationSeverityMedium,
			rdf.Severity_ERROR:   annotationSeverityHigh,
		},
		duplicates: map[string]struct{}{},
	}
}

// Post accepts a comment and holds it. Flush method actually posts comments to
// Bitbucket in batch.
func (r *ReportAnnotator) Post(_ context.Context, c *reviewdog.Comment) error {
	c.Result.Diagnostic.GetLocation().Path = filepath.ToSlash(
		filepath.Join(r.wd, c.Result.Diagnostic.GetLocation().GetPath()))
	r.muAnnotations.Lock()
	defer r.muAnnotations.Unlock()

	anot := r.annotationFromReviewDogComment(*c)

	// deduplicate event, because some reporters might report
	// it twice, and bitbucket api will complain on duplicated
	// external id of annotation
	if _, ok := r.duplicates[*anot.ExternalId]; !ok {
		r.annotations[c.ToolName] = append(r.annotations[c.ToolName], anot)
	}

	r.duplicates[*anot.ExternalId] = struct{}{}
	return nil
}

// Flush posts comments which has not been posted yet.
func (r *ReportAnnotator) Flush(ctx context.Context) error {
	r.muAnnotations.Lock()
	defer r.muAnnotations.Unlock()

	// create/update/annotate report per tool
	for tool, annotations := range r.annotations {
		reportID := reportID(reporter, tool)
		title := fmt.Sprintf("[%s] %s report", tool, reporter)
		if len(annotations) == 0 {
			// if no annotation, create Passed report
			if err := r.createOrUpdateReport(ctx, reportID, title, reportResultPassed); err != nil {
				return err
			}
			// and move one
			continue
		}

		// create report or update report first, with the failed status
		if err := r.createOrUpdateReport(ctx, reportID, title, reportResultFailed); err != nil {
			return err
		}

		// send annotations in batches, because of the api max payload size limit
		for start, annCount := 0, len(annotations); start < annCount; start += annotationsBatchSize {
			end := start + annotationsBatchSize

			if end > annCount {
				end = annCount
			}

			// add annotations to the report
			_, resp, err := r.cli.ReportsApi.BulkCreateOrUpdateAnnotations(
				ctx, r.owner, r.repo, r.sha, reportID,
			).Body(annotations[start:end]).Execute()

			if err := checkAPIError(err, resp, http.StatusOK); err != nil {
				return fmt.Errorf("bitbucket.BulkCreateOrUpdateAnnotations: %s", err)
			}
		}
	}

	return nil
}

func (r *ReportAnnotator) annotationFromReviewDogComment(c reviewdog.Comment) openapi.ReportAnnotation {
	a := openapi.NewReportAnnotation()
	switch c.ToolName {
	// TODO: different type of annotation based on tool?
	default:
		a.SetAnnotationType(annotationTypeCodeSmell)
	}

	// hash the output of linter and use it as external id
	a.SetExternalId(hashString(c.Result.Diagnostic.OriginalOutput))
	a.SetSummary(c.Result.Diagnostic.GetMessage())
	a.SetDetails(fmt.Sprintf(`[%s] %s`, c.ToolName, c.Result.Diagnostic.GetMessage()))
	a.SetLine(c.Result.Diagnostic.GetLocation().GetRange().GetStart().GetLine())
	a.SetPath(c.Result.Diagnostic.GetLocation().GetPath())
	if v, ok := r.severityMap[c.Result.Diagnostic.GetSeverity()]; ok {
		a.SetSeverity(v)
	}
	if link := c.Result.Diagnostic.GetCode().GetUrl(); link != "" {
		a.SetLink(link)
	}

	return *a
}

func (r *ReportAnnotator) createOrUpdateReport(ctx context.Context, redportID, title, reportStatus string) error {
	var report = openapi.NewReport()
	report.SetTitle(title)
	// TODO: different report types?
	report.SetReportType(reportTypeBug)
	report.SetReporter(reporter)
	report.SetLogoUrl(logoURL)
	report.SetResult(reportStatus)
	if reportStatus == reportResultPassed {
		report.SetDetails("Great news! Reviewdog couldn't spot any issues!")
	} else {
		report.SetDetails("Woof-Woof! This report generated for you by reviewdog")
	}

	_, resp, err := r.cli.ReportsApi.CreateOrUpdateReport(
		ctx, r.owner, r.repo, r.sha, redportID,
	).Body(*report).Execute()

	if err := checkAPIError(err, resp, http.StatusOK); err != nil {
		return fmt.Errorf("bitbucket.CreateOrUpdateReport: %s", err)
	}

	return nil
}

func hashString(str string) string {
	h := sha256.New()
	_, _ = h.Write([]byte(str))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func reportID(ids ...string) string {
	return strings.ReplaceAll(strings.ToLower(strings.Join(ids, "-")), " ", "_")
}
<|endoftext|>