re-add github.com/moul/anonuuid
This commit is contained in:
parent
aa75881ed5
commit
be1682d69f
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Manfred Touron
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
# Project-specific variables
|
||||
BINARIES ?= anonuuid
|
||||
CONVEY_PORT ?= 9042
|
||||
|
||||
|
||||
# Common variables
|
||||
SOURCES := $(shell find . -name "*.go")
|
||||
COMMANDS := $(shell go list ./... | grep -v /vendor/ | grep /cmd/)
|
||||
PACKAGES := $(shell go list ./... | grep -v /vendor/ | grep -v /cmd/)
|
||||
GOENV ?= GO15VENDOREXPERIMENT=1
|
||||
GO ?= $(GOENV) go
|
||||
GODEP ?= $(GOENV) godep
|
||||
USER ?= $(shell whoami)
|
||||
|
||||
|
||||
all: build
|
||||
|
||||
|
||||
.PHONY: build
|
||||
build: $(BINARIES)
|
||||
|
||||
|
||||
$(BINARIES): $(SOURCES)
|
||||
$(GO) build -o $@ ./cmd/$@
|
||||
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
$(GO) get -t .
|
||||
$(GO) test -v .
|
||||
|
||||
|
||||
.PHONY: godep-save
|
||||
godep-save:
|
||||
$(GODEP) save $(PACKAGES) $(COMMANDS)
|
||||
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(BINARIES)
|
||||
|
||||
|
||||
.PHONY: re
|
||||
re: clean all
|
||||
|
||||
|
||||
.PHONY: convey
|
||||
convey:
|
||||
$(GO) get github.com/smartystreets/goconvey
|
||||
goconvey -cover -port=$(CONVEY_PORT) -workDir="$(realpath .)" -depth=1
|
||||
|
||||
|
||||
.PHONY: cover
|
||||
cover: profile.out
|
||||
|
||||
|
||||
profile.out: $(SOURCES)
|
||||
rm -f $@
|
||||
$(GO) test -covermode=count -coverpkg=. -coverprofile=$@ .
|
||||
|
||||
|
||||
.PHONY: docker-build
|
||||
docker-build:
|
||||
go get github.com/laher/goxc
|
||||
rm -rf contrib/docker/linux_386
|
||||
for binary in $(BINARIES); do \
|
||||
goxc -bc="linux,386" -d . -pv contrib/docker -n $$binary xc; \
|
||||
mv contrib/docker/linux_386/$$binary contrib/docker/entrypoint; \
|
||||
docker build -t $(USER)/$$binary contrib/docker; \
|
||||
docker run -it --rm $(USER)/$$binary || true; \
|
||||
docker inspect --type=image --format="{{ .Id }}" moul/$$binary || true; \
|
||||
echo "Now you can run 'docker push $(USER)/$$binary'"; \
|
||||
done
|
|
@ -0,0 +1,170 @@
|
|||
# AnonUUID
|
||||
|
||||
[![Build Status](https://travis-ci.org/moul/anonuuid.svg)](https://travis-ci.org/moul/anonuuid)
|
||||
[![GoDoc](https://godoc.org/github.com/moul/anonuuid?status.svg)](https://godoc.org/github.com/moul/anonuuid)
|
||||
[![Coverage Status](https://coveralls.io/repos/moul/anonuuid/badge.svg?branch=master&service=github)](https://coveralls.io/github/moul/anonuuid?branch=master)
|
||||
|
||||
:wrench: Anonymize UUIDs outputs (written in Golang)
|
||||
|
||||
![AnonUUID Logo](https://raw.githubusercontent.com/moul/anonuuid/master/assets/anonuuid.png)
|
||||
|
||||
**anonuuid** anonymize an input string by replacing all UUIDs by an anonymized
|
||||
new one.
|
||||
|
||||
The fake UUIDs are cached, so if AnonUUID encounter the same real UUIDs multiple
|
||||
times, the translation will be the same.
|
||||
|
||||
## Usage
|
||||
|
||||
```console
|
||||
$ anonuuid --help
|
||||
NAME:
|
||||
anonuuid - Anonymize UUIDs outputs
|
||||
|
||||
USAGE:
|
||||
anonuuid [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.0.0-dev
|
||||
|
||||
AUTHOR(S):
|
||||
Manfred Touron <https://github.com/moul>
|
||||
|
||||
COMMANDS:
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--hexspeak Generate hexspeak style fake UUIDs
|
||||
--random, -r Generate random fake UUIDs
|
||||
--keep-beginning Keep first part of the UUID unchanged
|
||||
--keep-end Keep last part of the UUID unchanged
|
||||
--prefix, -p Prefix generated UUIDs
|
||||
--suffix Suffix generated UUIDs
|
||||
--help, -h show help
|
||||
--version, -v print the version
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Replace all UUIDs and cache the correspondance.
|
||||
|
||||
```command
|
||||
$ anonuuid git:(master) ✗ cat <<EOF | anonuuid
|
||||
VOLUMES_0_SERVER_ID=15573749-c89d-41dd-a655-16e79bed52e0
|
||||
VOLUMES_0_SERVER_NAME=hello
|
||||
VOLUMES_0_ID=c245c3cb-3336-4567-ada1-70cb1fe4eefe
|
||||
VOLUMES_0_SIZE=50000000000
|
||||
ORGANIZATION=fe1e54e8-d69d-4f7c-a9f1-42069e03da31
|
||||
TEST=15573749-c89d-41dd-a655-16e79bed52e0
|
||||
EOF
|
||||
VOLUMES_0_SERVER_ID=00000000-0000-0000-0000-000000000000
|
||||
VOLUMES_0_SERVER_NAME=hello
|
||||
VOLUMES_0_ID=11111111-1111-1111-1111-111111111111
|
||||
VOLUMES_0_SIZE=50000000000
|
||||
ORGANIZATION=22222222-2222-2222-2222-222222222222
|
||||
TEST=00000000-0000-0000-0000-000000000000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Inline
|
||||
|
||||
```command
|
||||
$ echo 'VOLUMES_0_SERVER_ID=15573749-c89d-41dd-a655-16e79bed52e0 VOLUMES_0_SERVER_NAME=bitrig1 VOLUMES_0_ID=c245c3cb-3336-4567-ada1-70cb1fe4eefe VOLUMES_0_SIZE=50000000000 ORGANIZATION=fe1e54e8-d69d-4f7c-a9f1-42069e03da31 TEST=15573749-c89d-41dd-a655-16e79bed52e0' | ./anonuuid
|
||||
VOLUMES_0_SERVER_ID=00000000-0000-0000-0000-000000000000 VOLUMES_0_SERVER_NAME=bitrig1 VOLUMES_0_ID=11111111-1111-1111-1111-111111111111 VOLUMES_0_SIZE=50000000000 ORGANIZATION=22222222-2222-2222-2222-222222222222 TEST=00000000-0000-0000-0000-000000000000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```command
|
||||
$ curl -s https://api.pathwar.net/achievements\?max_results\=2 | anonuuid | jq .
|
||||
{
|
||||
"_items": [
|
||||
{
|
||||
"_updated": "Thu, 30 Apr 2015 13:00:58 GMT",
|
||||
"description": "You",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "achievements/00000000-0000-0000-0000-000000000000",
|
||||
"title": "achievement"
|
||||
}
|
||||
},
|
||||
"_created": "Thu, 30 Apr 2015 13:00:58 GMT",
|
||||
"_id": "00000000-0000-0000-0000-000000000000",
|
||||
"_etag": "b1e9f850accfcb952c58384db41d89728890a69f",
|
||||
"name": "finish-20-levels"
|
||||
},
|
||||
{
|
||||
"_updated": "Thu, 30 Apr 2015 13:01:07 GMT",
|
||||
"description": "You",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "achievements/11111111-1111-1111-1111-111111111111",
|
||||
"title": "achievement"
|
||||
}
|
||||
},
|
||||
"_created": "Thu, 30 Apr 2015 13:01:07 GMT",
|
||||
"_id": "11111111-1111-1111-1111-111111111111",
|
||||
"_etag": "c346f5e1c4f7658f2dfc4124efa87aba909a9821",
|
||||
"name": "buy-30-levels"
|
||||
}
|
||||
],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "achievements?max_results=2",
|
||||
"title": "achievements"
|
||||
},
|
||||
"last": {
|
||||
"href": "achievements?max_results=2&page=23",
|
||||
"title": "last page"
|
||||
},
|
||||
"parent": {
|
||||
"href": "/",
|
||||
"title": "home"
|
||||
},
|
||||
"next": {
|
||||
"href": "achievements?max_results=2&page=2",
|
||||
"title": "next page"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"max_results": 2,
|
||||
"total": 46,
|
||||
"page": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
Using go
|
||||
|
||||
- `go get github.com/moul/anonuuid/...`
|
||||
|
||||
## Changelog
|
||||
|
||||
### master (unreleased)
|
||||
|
||||
* Add mutex to protect the cache field ([@QuentinPerez](https://github.com/QuentinPerez))
|
||||
* Switch from `Party` to `Godep`
|
||||
* Support of `--suffix=xxx`, `--keep-beginning` and `--keep-end` options ([#4](https://github.com/moul/anonuuid/issues/4))
|
||||
* Using **party** to stabilize vendor package versions ([#8](https://github.com/moul/anonuuid/issues/8))
|
||||
* Add homebrew package ([#6](https://github.com/moul/anonuuid/issues/6))
|
||||
|
||||
[full commits list](https://github.com/moul/anonuuid/compare/v1.0.0...master)
|
||||
|
||||
### [v1.0.0](https://github.com/moul/anonuuid/releases/tag/v1.0.0) (2015-10-07)
|
||||
|
||||
**Initial release**
|
||||
|
||||
#### Features
|
||||
|
||||
* Support of `--hexspeak` option
|
||||
* Support of `--random` option
|
||||
* Support of `--prefix` option
|
||||
* Anonymize input stream
|
||||
* Anonymize files
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
|
@ -0,0 +1,229 @@
|
|||
package anonuuid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// UUIDRegex is the regex used to find UUIDs in texts
|
||||
UUIDRegex = "[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}"
|
||||
)
|
||||
|
||||
// AnonUUID is the main structure, it contains the cache map and helpers
|
||||
type AnonUUID struct {
|
||||
cache map[string]string
|
||||
|
||||
guard sync.Mutex // cache guard
|
||||
|
||||
// Hexspeak flag will generate hexspeak style fake UUIDs
|
||||
Hexspeak bool
|
||||
|
||||
// Random flag will generate random fake UUIDs
|
||||
Random bool
|
||||
|
||||
// Prefix will be the beginning of all the generated UUIDs
|
||||
Prefix string
|
||||
|
||||
// Suffix will be the end of all the generated UUIDs
|
||||
Suffix string
|
||||
|
||||
// AllowNonUUIDInput tells FakeUUID to accept non UUID input string
|
||||
AllowNonUUIDInput bool
|
||||
|
||||
// KeepBeginning tells FakeUUID to let the beginning of the UUID as it is
|
||||
KeepBeginning bool
|
||||
|
||||
// KeepEnd tells FakeUUID to let the last part of the UUID as it is
|
||||
KeepEnd bool
|
||||
}
|
||||
|
||||
// Sanitize takes a string as input and return sanitized string
|
||||
func (a *AnonUUID) Sanitize(input string) string {
|
||||
r := regexp.MustCompile(UUIDRegex)
|
||||
|
||||
return r.ReplaceAllStringFunc(input, func(m string) string {
|
||||
parts := r.FindStringSubmatch(m)
|
||||
return a.FakeUUID(parts[0])
|
||||
})
|
||||
}
|
||||
|
||||
// FakeUUID takes a word (real UUID or standard string) and returns its corresponding (mapped) fakeUUID
|
||||
func (a *AnonUUID) FakeUUID(input string) string {
|
||||
if !a.AllowNonUUIDInput {
|
||||
err := IsUUID(input)
|
||||
if err != nil {
|
||||
return "invaliduuid"
|
||||
}
|
||||
}
|
||||
a.guard.Lock()
|
||||
defer a.guard.Unlock()
|
||||
if _, ok := a.cache[input]; !ok {
|
||||
|
||||
if a.KeepBeginning {
|
||||
a.Prefix = input[:8]
|
||||
}
|
||||
|
||||
if a.KeepEnd {
|
||||
a.Suffix = input[36-12:]
|
||||
}
|
||||
|
||||
if a.Prefix != "" {
|
||||
matched, err := regexp.MatchString("^[a-z0-9]+$", a.Prefix)
|
||||
if err != nil || !matched {
|
||||
a.Prefix = "invalidprefix"
|
||||
}
|
||||
}
|
||||
|
||||
if a.Suffix != "" {
|
||||
matched, err := regexp.MatchString("^[a-z0-9]+$", a.Suffix)
|
||||
if err != nil || !matched {
|
||||
a.Suffix = "invalsuffix"
|
||||
}
|
||||
}
|
||||
|
||||
var fakeUUID string
|
||||
var err error
|
||||
if a.Hexspeak {
|
||||
fakeUUID, err = GenerateHexspeakUUID(len(a.cache))
|
||||
} else if a.Random {
|
||||
fakeUUID, err = GenerateRandomUUID(10)
|
||||
} else {
|
||||
fakeUUID, err = GenerateLenUUID(len(a.cache))
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate an UUID: %v", err)
|
||||
}
|
||||
|
||||
if a.Prefix != "" {
|
||||
fakeUUID, err = PrefixUUID(a.Prefix, fakeUUID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if a.Suffix != "" {
|
||||
fakeUUID, err = SuffixUUID(a.Suffix, fakeUUID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: check for duplicates and retry
|
||||
|
||||
a.cache[input] = fakeUUID
|
||||
}
|
||||
return a.cache[input]
|
||||
}
|
||||
|
||||
// New returns a prepared AnonUUID structure
|
||||
func New() *AnonUUID {
|
||||
return &AnonUUID{
|
||||
cache: make(map[string]string),
|
||||
Hexspeak: false,
|
||||
Random: false,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
}
|
||||
|
||||
// PrefixUUID returns a prefixed UUID
|
||||
func PrefixUUID(prefix string, uuid string) (string, error) {
|
||||
uuidLetters := uuid[:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
|
||||
prefixedUUID, err := FormatUUID(prefix + uuidLetters)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return prefixedUUID, nil
|
||||
}
|
||||
|
||||
// SuffixUUID returns a suffixed UUID
|
||||
func SuffixUUID(suffix string, uuid string) (string, error) {
|
||||
uuidLetters := uuid[:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
|
||||
uuidLetters = uuidLetters[:32-len(suffix)] + suffix
|
||||
suffixedUUID, err := FormatUUID(uuidLetters)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return suffixedUUID, nil
|
||||
}
|
||||
|
||||
// IsUUID returns nil if the input is an UUID, else it returns an error
|
||||
func IsUUID(input string) error {
|
||||
matched, err := regexp.MatchString("^"+UUIDRegex+"$", input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !matched {
|
||||
return fmt.Errorf("String '%s' is not a valid UUID", input)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FormatUUID takes a string in input and return an UUID formatted string by repeating the string and placing dashes if necessary
|
||||
func FormatUUID(part string) (string, error) {
|
||||
if len(part) < 1 {
|
||||
return "", fmt.Errorf("Empty UUID")
|
||||
}
|
||||
if len(part) < 32 {
|
||||
part = strings.Repeat(part, 32)
|
||||
}
|
||||
if len(part) > 32 {
|
||||
part = part[:32]
|
||||
}
|
||||
uuid := part[:8] + "-" + part[8:12] + "-1" + part[13:16] + "-" + part[16:20] + "-" + part[20:32]
|
||||
|
||||
err := IsUUID(uuid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// GenerateRandomUUID returns an UUID based on random strings
|
||||
func GenerateRandomUUID(length int) (string, error) {
|
||||
var letters = []rune("abcdef0123456789")
|
||||
|
||||
b := make([]rune, length)
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return FormatUUID(string(b))
|
||||
}
|
||||
|
||||
// GenerateHexspeakUUID returns an UUID formatted string containing hexspeak words
|
||||
func GenerateHexspeakUUID(i int) (string, error) {
|
||||
if i < 0 {
|
||||
i = -i
|
||||
}
|
||||
hexspeaks := []string{
|
||||
"0ff1ce",
|
||||
"31337",
|
||||
"4b1d",
|
||||
"badc0de",
|
||||
"badcafe",
|
||||
"badf00d",
|
||||
"deadbabe",
|
||||
"deadbeef",
|
||||
"deadc0de",
|
||||
"deadfeed",
|
||||
"fee1bad",
|
||||
}
|
||||
return FormatUUID(hexspeaks[i%len(hexspeaks)])
|
||||
}
|
||||
|
||||
// GenerateLenUUID returns an UUID formatted string based on an index number
|
||||
func GenerateLenUUID(i int) (string, error) {
|
||||
if i < 0 {
|
||||
i = 2<<29 + i
|
||||
}
|
||||
return FormatUUID(fmt.Sprintf("%x", i))
|
||||
}
|
|
@ -2172,6 +2172,12 @@
|
|||
"revision": "92573fe8d000a145bfebc03a16bc22b34945867f",
|
||||
"revisionTime": "2016-10-03T17:45:16Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "KhOVzKefFYORHdIVe+/gNAHB23A=",
|
||||
"path": "github.com/moul/anonuuid",
|
||||
"revision": "609b752a95effbbef26d134ac18ed6f57e01b98e",
|
||||
"revisionTime": "2016-02-22T16:21:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "/iig5lYSPCL3C8J7e4nTAevYNDE=",
|
||||
"comment": "v0.2.0-8-g841842b",
|
||||
|
|
Loading…
Reference in New Issue