Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ql/lib/codeql/bicep/Frameworks.qll
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import frameworks.Microsoft.Cache
import frameworks.Microsoft.Compute
import frameworks.Microsoft.General
import frameworks.Microsoft.Network
import frameworks.Microsoft.Storage
import frameworks.Microsoft.Databases
Expand Down
239 changes: 239 additions & 0 deletions ql/lib/codeql/bicep/frameworks/Microsoft/Cache.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
private import bicep
private import codeql.bicep.Concepts

module Cache {
abstract class CacheResource extends Resource { }

/**
* Represents an Azure Cache for Redis resource.
*/
class RedisCacheResource extends CacheResource, Resource {
/**
* Constructs a RedisCacheResource for Microsoft.Cache/Redis resources.
*/
RedisCacheResource() { this.getResourceType().regexpMatch("^Microsoft.Cache/Redis@.*") }

/**
* Returns the properties object for the Redis cache resource.
*/
CacheProperties::Properties getProperties() { result = this.getProperty("properties") }

CacheProperties::RedisConfiguration getRedisConfiguration() {
result = this.getProperties().getProperty("redisConfiguration")
}

/**
* Returns the SKU of the Redis cache.
*/
Sku getSku() { result = this.getProperty("sku") }

/**
* Returns the Redis version.
*/
string redisVersion() {
result = this.getProperties().getProperty("redisVersion").(StringLiteral).getValue()
}

/**
* Returns true if non-SSL port is enabled.
*/
boolean enableNonSslPort() {
result = this.getProperties().getProperty("enableNonSslPort").(Boolean).getBool()
}

/**
* Returns the publicNetworkAccess property, if present.
*/
string publicNetworkAccess() {
result = this.getProperties().getProperty("publicNetworkAccess").(StringLiteral).getValue()
}

/**
* Returns a string representation of the Redis cache resource.
*/
override string toString() { result = "RedisCacheResource" }
}

/**
* Represents a public Azure Cache for Redis resource (public network access enabled).
*/
class PublicRedisCacheResource extends PublicResource {
private RedisCacheResource redisCache;

/**
* Constructs a PublicRedisCacheResource if the Redis cache has public network access enabled.
*/
PublicRedisCacheResource() {
redisCache.publicNetworkAccess() = "Enabled" and
this = redisCache
}

/**
* Returns the property that indicates public access for the Redis cache resource.
*/
override Expr getPublicAccessProperty() {
result = redisCache.getProperties().getProperty("publicNetworkAccess")
}
}

module CacheProperties {
/**
* Represents the properties object for a Redis cache resource.
*/
class Properties extends Object {
private RedisCacheResource redisCache;

/**
* Constructs a Properties object for the given Redis cache resource.
*/
Properties() { this = redisCache.getProperty("properties") }

/**
* Returns the parent RedisCacheResource.
*/
RedisCacheResource getRedisCacheResource() { result = redisCache }

string toString() { result = "CacheProperties" }
}

/**
* Represents the redisConfiguration object for Azure Cache for Redis.
* Provides accessors for all supported redisConfiguration properties.
*/
class RedisConfiguration extends Object {
private Properties properties;

/**
* Constructs a RedisConfiguration object for the given properties.
*/
RedisConfiguration() { this = properties.getProperty("redisConfiguration") }

/** Returns the 'aad-enabled' property as a StringLiteral, if present. */
StringLiteral getAadEnabled() { result = this.getProperty("aad-enabled") }

/** Returns the 'aad-enabled' property as a string, if present. */
string aadEnabled() { result = this.getAadEnabled().getValue() }

/** Returns the 'aof-backup-enabled' property as a StringLiteral, if present. */
StringLiteral getAofBackupEnabled() { result = this.getProperty("aof-backup-enabled") }

/** Returns the 'aof-backup-enabled' property as a string, if present. */
string aofBackupEnabled() { result = this.getAofBackupEnabled().getValue() }

/** Returns the 'aof-storage-connection-string-0' property as a StringLiteral, if present. */
StringLiteral getAofStorageConnectionString0() {
result = this.getProperty("aof-storage-connection-string-0")
}

/** Returns the 'aof-storage-connection-string-0' property as a string, if present. */
string aofStorageConnectionString0() {
result = this.getAofStorageConnectionString0().getValue()
}

/** Returns the 'aof-storage-connection-string-1' property as a StringLiteral, if present. */
StringLiteral getAofStorageConnectionString1() {
result = this.getProperty("aof-storage-connection-string-1")
}

/** Returns the 'aof-storage-connection-string-1' property as a string, if present. */
string aofStorageConnectionString1() {
result = this.getAofStorageConnectionString1().getValue()
}

/** Returns the 'authnotrequired' property as a StringLiteral, if present. */
StringLiteral getAuthNotRequired() { result = this.getProperty("authnotrequired") }

/** Returns the 'authnotrequired' property as a string, if present. */
string authNotRequired() { result = this.getAuthNotRequired().getValue() }

/** Returns the 'maxfragmentationmemory-reserved' property as a StringLiteral, if present. */
StringLiteral getMaxFragmentationMemoryReserved() {
result = this.getProperty("maxfragmentationmemory-reserved")
}

/** Returns the 'maxfragmentationmemory-reserved' property as a string, if present. */
string maxFragmentationMemoryReserved() {
result = this.getMaxFragmentationMemoryReserved().getValue()
}

/** Returns the 'maxmemory-delta' property as a StringLiteral, if present. */
StringLiteral getMaxMemoryDelta() { result = this.getProperty("maxmemory-delta") }

/** Returns the 'maxmemory-delta' property as a string, if present. */
string maxMemoryDelta() { result = this.getMaxMemoryDelta().getValue() }

/** Returns the 'maxmemory-policy' property as a StringLiteral, if present. */
StringLiteral getMaxMemoryPolicy() { result = this.getProperty("maxmemory-policy") }

/** Returns the 'maxmemory-policy' property as a string, if present. */
string maxMemoryPolicy() { result = this.getMaxMemoryPolicy().getValue() }

/** Returns the 'maxmemory-reserved' property as a StringLiteral, if present. */
StringLiteral getMaxMemoryReserved() { result = this.getProperty("maxmemory-reserved") }

/** Returns the 'maxmemory-reserved' property as a string, if present. */
string maxMemoryReserved() { result = this.getMaxMemoryReserved().getValue() }

/** Returns the 'notify-keyspace-events' property as a StringLiteral, if present. */
StringLiteral getNotifyKeyspaceEvents() {
result = this.getProperty("notify-keyspace-events")
}

/** Returns the 'notify-keyspace-events' property as a string, if present. */
string notifyKeyspaceEvents() { result = this.getNotifyKeyspaceEvents().getValue() }

/** Returns the 'preferred-data-persistence-auth-method' property as a StringLiteral, if present. */
StringLiteral getPreferredDataPersistenceAuthMethod() {
result = this.getProperty("preferred-data-persistence-auth-method")
}

/** Returns the 'preferred-data-persistence-auth-method' property as a string, if present. */
string preferredDataPersistenceAuthMethod() {
result = this.getPreferredDataPersistenceAuthMethod().getValue()
}

/** Returns the 'rdb-backup-enabled' property as a StringLiteral, if present. */
StringLiteral getRdbBackupEnabled() { result = this.getProperty("rdb-backup-enabled") }

/** Returns the 'rdb-backup-enabled' property as a string, if present. */
string rdbBackupEnabled() { result = this.getRdbBackupEnabled().getValue() }

/** Returns the 'rdb-backup-frequency' property as a StringLiteral, if present. */
StringLiteral getRdbBackupFrequency() { result = this.getProperty("rdb-backup-frequency") }

/** Returns the 'rdb-backup-frequency' property as a string, if present. */
string rdbBackupFrequency() { result = this.getRdbBackupFrequency().getValue() }

/** Returns the 'rdb-backup-max-snapshot-count' property as a StringLiteral, if present. */
StringLiteral getRdbBackupMaxSnapshotCount() {
result = this.getProperty("rdb-backup-max-snapshot-count")
}

/** Returns the 'rdb-backup-max-snapshot-count' property as a string, if present. */
string rdbBackupMaxSnapshotCount() { result = this.getRdbBackupMaxSnapshotCount().getValue() }

/** Returns the 'rdb-storage-connection-string' property as a StringLiteral, if present. */
StringLiteral getRdbStorageConnectionString() {
result = this.getProperty("rdb-storage-connection-string")
}

/** Returns the 'rdb-storage-connection-string' property as a string, if present. */
string rdbStorageConnectionString() {
result = this.getRdbStorageConnectionString().getValue()
}

/** Returns the 'storage-subscription-id' property as a StringLiteral, if present. */
StringLiteral getStorageSubscriptionId() {
result = this.getProperty("storage-subscription-id")
}

/** Returns the 'storage-subscription-id' property as a string, if present. */
string storageSubscriptionId() { result = this.getStorageSubscriptionId().getValue() }

/**
* Returns a string representation of the RedisConfiguration object.
*/
string toString() { result = "RedisConfiguration" }
}
}
}
15 changes: 0 additions & 15 deletions ql/lib/codeql/bicep/frameworks/Microsoft/Databases.qll
Original file line number Diff line number Diff line change
Expand Up @@ -211,21 +211,6 @@ module Databases {
override string databaseType() { result = "datalakestore" }
}

/**
* Represents an Azure Cache for Redis resource.
*/
class RedisCaches extends DatabaseResource, Resource {
/**
* Constructs an instance for Azure Cache for Redis resources.
*/
RedisCaches() { this.getResourceType().regexpMatch("^Microsoft.Cache/Redis@.*") }

/**
* Returns the type of the database resource ("redis").
*/
override string databaseType() { result = "redis" }
}

/**
* Represents an Azure Data Explorer (Kusto) cluster resource.
*/
Expand Down
28 changes: 28 additions & 0 deletions ql/lib/codeql/bicep/frameworks/Microsoft/General.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
private import bicep

class Sku extends Object {
private Resource resource;

/**
* Constructs a Sku object for the given resource.
*/
Sku() { this = resource.getProperty("sku") }

/**
* Returns the SKU name (e.g., Basic, Standard, Premium).
*/
string getName() {
result = this.getProperty("name").(StringLiteral).getValue()
}

/**
* Returns the SKU tier (e.g., Basic, Standard, Premium).
*/
string getTier() {
result = this.getProperty("tier").(StringLiteral).getValue()
}

string toString() {
result = "SKU"
}
}
4 changes: 4 additions & 0 deletions ql/test/library-tests/frameworks/cache/Cache.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cache
| app.bicep:1:1:17:1 | RedisCacheResource |
cacheConfig
| app.bicep:1:1:17:1 | RedisCacheResource | app.bicep:13:25:15:5 | RedisConfiguration |
9 changes: 9 additions & 0 deletions ql/test/library-tests/frameworks/cache/Cache.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import bicep

query predicate cache(Cache::CacheResource cache) { any() }

query predicate cacheConfig(
Cache::RedisCacheResource cache, Cache::CacheProperties::RedisConfiguration config
) {
cache.getRedisConfiguration() = config
}
17 changes: 17 additions & 0 deletions ql/test/library-tests/frameworks/cache/app.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
resource redisCache 'Microsoft.Cache/Redis@2023-04-01' = {
name: 'myRedisCache'
location: resourceGroup().location
sku: {
name: 'Standard'
family: 'C'
capacity: 1
}
properties: {
enableNonSslPort: false
minimumTlsVersion: '1.2'
publicNetworkAccess: 'Enabled'
redisConfiguration: {
maxmemory-policy: 'allkeys-lru'
}
}
}
5 changes: 2 additions & 3 deletions ql/test/library-tests/frameworks/databases/Databases.expected
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@
| app.bicep:98:1:111:1 | DatabaseResource[mysql] |
| app.bicep:114:1:124:1 | DatabaseResource[mariadb] |
| app.bicep:127:1:131:1 | DatabaseResource[datalakestore] |
| app.bicep:134:1:144:1 | DatabaseResource[redis] |
| app.bicep:147:1:156:1 | DatabaseResource[kusto] |
| app.bicep:159:1:166:1 | DatabaseResource[arc-sql-managed-instance] |
| app.bicep:134:1:143:1 | DatabaseResource[kusto] |
| app.bicep:146:1:153:1 | DatabaseResource[arc-sql-managed-instance] |
13 changes: 0 additions & 13 deletions ql/test/library-tests/frameworks/databases/app.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,6 @@ resource datalakeStore 'Microsoft.DataLakeStore/accounts@2016-11-01' = {
properties: {}
}

// Azure Cache for Redis
resource redisCache 'Microsoft.Cache/Redis@2023-04-01' = {
name: 'rediscache1'
location: 'eastus'
properties: {
sku: {
name: 'Basic'
family: 'C'
capacity: 0
}
}
}

// Azure Data Explorer (Kusto)
resource kustoCluster 'Microsoft.Kusto/Clusters@2023-05-02' = {
name: 'kustocluster1'
Expand Down