Skip to content

Commit f80259f

Browse files
Transcribe docker reference parsing and introduce dockerFile detector (#114)
Transcribe docker reference parsing and introduce dockerFile detectors/submission Co-authored-by: Jamie Magee <jamagee@microsoft.com>
1 parent 0c86fef commit f80259f

12 files changed

Lines changed: 886 additions & 1 deletion

File tree

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,6 @@
4242
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="4.9.0"/>
4343
<PackageVersion Include="yamldotnet" Version="11.2.1"/>
4444
<PackageVersion Include="Faker.net" Version="2.0.154"/>
45+
<PackageVersion Include="Valleysoft.DockerfileModel" Version="1.0.0"/>
4546
</ItemGroup>
4647
</Project>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System.Collections.Generic;
2+
3+
namespace Microsoft.ComponentDetection.Common
4+
{
5+
public class DigestUtility
6+
{
7+
private static readonly Dictionary<string, int> AlgorithmsSizes = new Dictionary<string, int>()
8+
{
9+
{ "sha256", 32 },
10+
{ "sha384", 48 },
11+
{ "sha512", 64 },
12+
};
13+
14+
public static bool CheckDigest(string digest, bool throwError = true)
15+
{
16+
var indexOfColon = digest.IndexOf(':');
17+
if (indexOfColon < 0 ||
18+
indexOfColon + 1 == digest.Length ||
19+
!DockerRegex.AnchoredDigestRegexp.IsMatch(digest))
20+
{
21+
if (throwError)
22+
{
23+
throw new InvalidDigestFormatError(digest);
24+
}
25+
26+
return false;
27+
}
28+
29+
string algorithm = digest.Substring(0, indexOfColon);
30+
31+
if (!AlgorithmsSizes.ContainsKey(algorithm))
32+
{
33+
if (throwError)
34+
{
35+
throw new UnsupportedAlgorithmError(digest);
36+
}
37+
38+
return false;
39+
}
40+
41+
if (AlgorithmsSizes[algorithm] * 2 != (digest.Length - indexOfColon - 1))
42+
{
43+
if (throwError)
44+
{
45+
throw new InvalidDigestLengthError(digest);
46+
}
47+
48+
return false;
49+
}
50+
51+
return true;
52+
}
53+
}
54+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using System;
2+
3+
#pragma warning disable SA1402
4+
namespace Microsoft.ComponentDetection.Common
5+
{
6+
public class DockerReferenceException : Exception
7+
{
8+
public DockerReferenceException(string reference, string exceptionErrorMessage)
9+
: base($"Error while parsing docker reference {reference} : {exceptionErrorMessage}")
10+
{
11+
}
12+
}
13+
14+
// ReferenceInvalidFormat represents an error while trying to parse a string as a reference.
15+
public class ReferenceInvalidFormatException : DockerReferenceException
16+
{
17+
private const string ErrorMessage = "invalid reference format";
18+
19+
public ReferenceInvalidFormatException(string reference)
20+
: base(reference, ErrorMessage)
21+
{
22+
}
23+
}
24+
25+
// TagInvalidFormat represents an error while trying to parse a string as a tag.
26+
public class ReferenceTagInvalidFormatException : DockerReferenceException
27+
{
28+
private const string ErrorMessage = "invalid tag format";
29+
30+
public ReferenceTagInvalidFormatException(string reference)
31+
: base(reference, ErrorMessage)
32+
{
33+
}
34+
}
35+
36+
// DigestInvalidFormat represents an error while trying to parse a string as a tag.
37+
public class ReferenceDigestInvalidFormatException : DockerReferenceException
38+
{
39+
private const string ErrorMessage = "invalid digest format";
40+
41+
public ReferenceDigestInvalidFormatException(string reference)
42+
: base(reference, ErrorMessage)
43+
{
44+
}
45+
}
46+
47+
// NameContainsUppercase is returned for invalid repository names that contain uppercase characters.
48+
public class ReferenceNameContainsUppercaseException : DockerReferenceException
49+
{
50+
private const string ErrorMessage = "repository name must be lowercase";
51+
52+
public ReferenceNameContainsUppercaseException(string reference)
53+
: base(reference, ErrorMessage)
54+
{
55+
}
56+
}
57+
58+
// NameEmpty is returned for empty, invalid repository names.
59+
public class ReferenceNameEmptyException : DockerReferenceException
60+
{
61+
private const string ErrorMessage = "repository name must have at least one component";
62+
63+
public ReferenceNameEmptyException(string reference)
64+
: base(reference, ErrorMessage)
65+
{
66+
}
67+
}
68+
69+
// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
70+
public class ReferenceNameTooLongException : DockerReferenceException
71+
{
72+
private const string ErrorMessage = "repository name must not be more than 255 characters";
73+
74+
public ReferenceNameTooLongException(string reference)
75+
: base(reference, ErrorMessage)
76+
{
77+
}
78+
}
79+
80+
// ErrNameNotCanonical is returned when a name is not canonical.
81+
public class ReferenceNameNotCanonicalException : DockerReferenceException
82+
{
83+
private const string ErrorMessage = "repository name must be canonical";
84+
85+
public ReferenceNameNotCanonicalException(string reference)
86+
: base(reference, ErrorMessage)
87+
{
88+
}
89+
}
90+
91+
public class InvalidDigestFormatError : DockerReferenceException
92+
{
93+
private const string ErrorMessage = "invalid digest format";
94+
95+
public InvalidDigestFormatError(string reference)
96+
: base(reference, ErrorMessage)
97+
{
98+
}
99+
}
100+
101+
public class UnsupportedAlgorithmError : DockerReferenceException
102+
{
103+
private const string ErrorMessage = "unsupported digest algorithm";
104+
105+
public UnsupportedAlgorithmError(string reference)
106+
: base(reference, ErrorMessage)
107+
{
108+
}
109+
}
110+
111+
public class InvalidDigestLengthError : DockerReferenceException
112+
{
113+
private const string ErrorMessage = "invalid checksum digest length";
114+
115+
public InvalidDigestLengthError(string reference)
116+
: base(reference, ErrorMessage)
117+
{
118+
}
119+
}
120+
}

0 commit comments

Comments
 (0)