Compare commits

..

5 Commits

Author SHA1 Message Date
5eedcff042 add rand package, utilities for math/rand. 2020-06-02 17:26:17 -07:00
Kyle Isom
6ac8eb04b4 Updated by OWASP Threat Dragon 2020-03-05 15:29:57 -08:00
Kyle Isom
4a4e4cd3fd Updated by OWASP Threat Dragon 2020-03-05 12:20:49 -08:00
Kyle Isom
1207093a56 Created by OWASP Threat Dragon 2020-03-05 12:19:57 -08:00
2b6ae03d1a config: add a Require message.
Also update explanation of the intended use-case for this package.
2020-03-02 17:36:29 -08:00
4 changed files with 482 additions and 0 deletions

View File

@@ -0,0 +1,333 @@
{
"summary": {
"title": "goutils threat model",
"owner": "K",
"description": "HTF COMPUTER DO WHAT COMPUTER DO"
},
"detail": {
"contributors": [],
"diagrams": [
{
"title": "COMPUTRONICS",
"thumbnail": "./public/content/images/thumbnail.jpg",
"id": 0,
"diagramJson": {
"cells": [
{
"type": "tm.Process",
"size": {
"width": 100,
"height": 100
},
"position": {
"x": 235,
"y": 346
},
"angle": 0,
"id": "44f457bb-4c3c-45a4-8c49-1556afb6fe2a",
"z": 1,
"hasOpenThreats": false,
"attrs": {
".element-shape": {
"class": "element-shape hasNoOpenThreats isInScope"
},
"text": {
"text": "DOING THE\nTHING"
},
".element-text": {
"class": "element-text hasNoOpenThreats isInScope"
}
}
},
{
"type": "tm.Actor",
"size": {
"width": 160,
"height": 80
},
"position": {
"x": 239,
"y": 31
},
"angle": 0,
"id": "f5cdeb80-8c89-4af1-8a5d-c23e9dda81dd",
"z": 2,
"hasOpenThreats": true,
"threats": [
{
"status": "Open",
"severity": "Medium",
"title": "Creepering",
"type": "Denial of service",
"description": "Creeping and what not.",
"mitigation": "Banishment."
}
],
"attrs": {
".element-shape": {
"class": "element-shape hasOpenThreats isInScope"
},
"text": {
"text": "the darkness"
},
".element-text": {
"class": "element-text hasOpenThreats isInScope"
}
}
},
{
"type": "tm.Store",
"size": {
"width": 160,
"height": 80
},
"position": {
"x": 413,
"y": 368
},
"angle": 0,
"id": "0132401e-9bca-497d-8a04-7bfa64f9b548",
"z": 3,
"hasOpenThreats": false,
"attrs": {
".element-shape": {
"class": "element-shape hasNoOpenThreats isInScope"
},
"text": {
"text": "crown jewels"
},
".element-text": {
"class": "element-text hasNoOpenThreats isInScope"
}
}
},
{
"type": "tm.Actor",
"size": {
"width": 160,
"height": 80
},
"position": {
"x": 384,
"y": 473
},
"angle": 0,
"id": "b2988659-754c-452d-9ef5-a2c766792a52",
"z": 4,
"hasOpenThreats": false,
"attrs": {
".element-shape": {
"class": "element-shape hasNoOpenThreats isInScope"
},
"text": {
"text": "civilians"
},
".element-text": {
"class": "element-text hasNoOpenThreats isInScope"
}
}
},
{
"type": "tm.Actor",
"size": {
"width": 160,
"height": 80
},
"position": {
"x": 390,
"y": 251
},
"angle": 0,
"id": "45ed7d67-2d9f-4a7b-a5d2-a222beb1ba02",
"z": 5,
"hasOpenThreats": false,
"attrs": {
".element-shape": {
"class": "element-shape hasNoOpenThreats isInScope"
},
"text": {
"text": "captain america"
},
".element-text": {
"class": "element-text hasNoOpenThreats isInScope"
}
}
},
{
"type": "tm.Boundary",
"smooth": true,
"source": {
"x": 70,
"y": 212
},
"target": {
"x": 773,
"y": 181
},
"vertices": [],
"id": "675f56fc-ec5a-48f1-83d8-e65bafee112c",
"z": 6,
"attrs": {}
},
{
"type": "tm.Flow",
"smooth": true,
"source": {
"id": "b2988659-754c-452d-9ef5-a2c766792a52"
},
"target": {
"id": "44f457bb-4c3c-45a4-8c49-1556afb6fe2a"
},
"vertices": [
{
"x": 389,
"y": 462
},
{
"x": 375,
"y": 459
},
{
"x": 359,
"y": 441
}
],
"id": "a841a516-7f81-41c5-a5d4-832655f5e219",
"labels": [
{
"position": 0.5,
"attrs": {
"text": {
"text": "request",
"font-weight": "400",
"font-size": "small"
}
}
}
],
"z": 7,
"hasOpenThreats": false,
"isPublicNetwork": true,
"isEncrypted": true,
"attrs": {
".marker-target": {
"class": "marker-target hasNoOpenThreats isInScope"
},
".connection": {
"class": "connection hasNoOpenThreats isInScope"
}
}
},
{
"type": "tm.Flow",
"smooth": true,
"source": {
"id": "44f457bb-4c3c-45a4-8c49-1556afb6fe2a"
},
"target": {
"id": "0132401e-9bca-497d-8a04-7bfa64f9b548"
},
"vertices": [],
"id": "f4181dae-fcad-44c7-ad98-19b5bb1b9c84",
"labels": [
{
"position": 0.5,
"attrs": {
"text": {
"text": "cogitate",
"font-weight": "400",
"font-size": "small"
}
}
}
],
"z": 8,
"hasOpenThreats": false,
"attrs": {
".marker-target": {
"class": "marker-target hasNoOpenThreats isInScope"
},
".connection": {
"class": "connection hasNoOpenThreats isInScope"
}
}
},
{
"type": "tm.Flow",
"smooth": true,
"source": {
"id": "45ed7d67-2d9f-4a7b-a5d2-a222beb1ba02"
},
"target": {
"id": "0132401e-9bca-497d-8a04-7bfa64f9b548"
},
"vertices": [],
"id": "01353067-ce16-4a19-abb7-ce47edc7e309",
"labels": [
{
"position": 0.5,
"attrs": {
"text": {
"text": "adjudicate",
"font-weight": "400",
"font-size": "small"
}
}
}
],
"z": 9,
"hasOpenThreats": false,
"attrs": {
".marker-target": {
"class": "marker-target hasNoOpenThreats isInScope"
},
".connection": {
"class": "connection hasNoOpenThreats isInScope"
}
}
},
{
"type": "tm.Flow",
"smooth": true,
"source": {
"id": "45ed7d67-2d9f-4a7b-a5d2-a222beb1ba02"
},
"target": {
"id": "44f457bb-4c3c-45a4-8c49-1556afb6fe2a"
},
"vertices": [],
"id": "5298f767-1675-4ba3-b450-e2a5aad62452",
"labels": [
{
"position": 0.5,
"attrs": {
"text": {
"text": "assimilate",
"font-weight": "400",
"font-size": "small"
}
}
}
],
"z": 10,
"hasOpenThreats": false,
"attrs": {
".marker-target": {
"class": "marker-target hasNoOpenThreats isInScope"
},
".connection": {
"class": "connection hasNoOpenThreats isInScope"
}
}
}
]
},
"size": {
"height": 590,
"width": 948.910888671875
}
}
],
"reviewer": "K"
}
}

View File

@@ -1,6 +1,11 @@
// Package config implements a simple global configuration system that
// supports a file with key=value pairs and environment variables. Note
// that the config system is global.
//
// This package is intended to be used for small daemons: some configuration
// file is optionally populated at program start, then this is used to
// transparently look up configuration values from either that file or the
// environment.
package config
import (
@@ -82,3 +87,24 @@ func GetDefault(key, def string) string {
}
return def
}
// Require retrieves a value from either a configuration file or the
// environment. If the key isn't present, it will call log.Fatal, printing
// the missing key.
func Require(key string) string {
if v, ok := vars[key]; ok {
return v
}
v, ok := os.LookupEnv(prefix + key)
if !ok {
var envMessage string
if prefix != "" {
envMessage = " (note: looked for the key " + prefix + key
envMessage += " in the local env)"
}
log.Fatalf("missing required configuration value %s%s", key, envMessage)
}
return v
}

49
rand/rand.go Normal file
View File

@@ -0,0 +1,49 @@
// Package rand contains utilities for interacting with math/rand, including
// seeding from a random sed.
package rand
import (
"crypto/rand"
"encoding/binary"
mrand "math/rand"
)
// CryptoUint64 generates a cryptographically-secure 64-bit integer.
func CryptoUint64() (uint64, error) {
bs := make([]byte, 8)
_, err := rand.Read(bs)
if err != nil {
return 0, err
}
return binary.BigEndian.Uint64(bs), nil
}
// Seed initialises the non-cryptographic PRNG with a random,
// cryptographically secure value. This is done just as a good
// way to make this random. The returned 64-bit value is the seed.
func Seed() (uint64, error) {
seed, err := CryptoUint64()
if err != nil {
return 0, err
}
// NB: this is permitted.
mrand.Seed(int64(seed))
return seed, nil
}
// Int is a wrapper for math.Int so only one package needs to be imported.
func Int() int {
return mrand.Int()
}
// Intn is a wrapper for math.Intn so only one package needs to be imported.
func Intn(max int) int {
return mrand.Intn(max)
}
// Intn2 returns a random value between min and max, inclusive.
func Intn2(min, max int) int {
return Intn(max-min) + min
}

74
rand/rand_test.go Normal file
View File

@@ -0,0 +1,74 @@
package rand
import (
"fmt"
mrand "math/rand"
"testing"
)
func TestCryptoUint64(t *testing.T) {
n1, err := CryptoUint64()
if err != nil {
t.Fatal(err)
}
n2, err := CryptoUint64()
if err != nil {
t.Fatal(err)
}
// This has such a low chance of occurring that it's likely to be
// indicative of a bad CSPRNG.
if n1 == n2 {
t.Fatalf("repeated random uint64s: %d", n1)
}
}
func TestIntn(t *testing.T) {
expected := []int{3081, 4887, 4847, 1059, 3081}
mrand.Seed(1)
for i := 0; i < 5; i++ {
n := Intn2(1000, 5000)
if n != expected[i] {
fmt.Printf("invalid sequence at %d: expected %d, have %d", i, expected[i], n)
}
}
}
func TestSeed(t *testing.T) {
seed1, err := Seed()
if err != nil {
t.Fatal(err)
}
var seed2 uint64
n1 := Int()
tries := 0
for {
seed2, err = Seed()
if err != nil {
t.Fatal(err)
}
if seed1 != seed2 {
break
}
tries++
if tries > 3 {
t.Fatal("can't generate two unique seeds")
}
}
n2 := Int()
// Again, this not impossible, merely statistically improbably and a
// potential canary for RNG issues.
if n1 == n2 {
t.Fatalf("repeated integers fresh from two unique seeds: %d/%d -> %d",
seed1, seed2, n1)
}
}