class RandomString(resource.Resource): ''' A resource which generates a random string. This is useful for configuring passwords and secrets on services. ''' properties_schema = { 'length': properties.Schema(properties.INTEGER, _('Length of the string to generate.'), default=32, constraints=[properties.Range(1, 512)]), 'sequence': properties.Schema( properties.STRING, _('Sequence of characters to build the random string from.'), default='lettersdigits', constraints=[ properties.AllowedValues( ('lettersdigits', 'letters', 'lowercase', 'uppercase', 'digits', 'hexdigits', 'octdigits')) ]), 'salt': properties.Schema( properties.STRING, _('Value which can be set or changed on stack update to trigger ' 'the resource for replacement with a new random string . ' 'The salt value itself is ignored by the random generator.')) } attributes_schema = { 'value': _('The random string generated by this resource'), } _sequences = { 'lettersdigits': string.ascii_letters + string.digits, 'letters': string.ascii_letters, 'lowercase': string.ascii_lowercase, 'uppercase': string.ascii_uppercase, 'digits': string.digits, 'hexdigits': string.digits + 'ABCDEF', 'octdigits': string.octdigits } @staticmethod def _generate_random_string(sequence, length): rand = random.SystemRandom() return ''.join(rand.choice(sequence) for x in xrange(length)) def handle_create(self): length = self.properties.get('length') sequence = self._sequences[self.properties.get('sequence')] random_string = self._generate_random_string(sequence, length) db_api.resource_data_set(self, 'value', random_string, redact=True) def _resolve_attribute(self, name): if name == 'value': return db_api.resource_data_get(self, 'value')
def test_range_max_fail(self): r = properties.Range(max=5, description='a range') self.assertRaises(ValueError, r.validate, 6)
def test_range_validate(self): r = properties.Range(min=5, max=5, description='a range') r.validate(5)
def test_range_max_schema(self): d = {'range': {'max': 10}, 'description': 'a range'} r = properties.Range(max=10, description='a range') self.assertEqual(d, dict(r))
def test_range_min_schema(self): d = {'range': {'min': 5}, 'description': 'a range'} r = properties.Range(min=5, description='a range') self.assertEqual(d, dict(r))
def test_range_invalid_type(self): self.assertRaises(properties.InvalidPropertySchemaError, properties.Schema, 'String', constraints=[properties.Range(1, 10)])